Closed jellohouse closed 11 months ago
I also have a very similar use-case. Were you able to achieve what you needed @jellohouse?
I ended up using const { getToken } = useAuth();
in my popup and then saving the result from const userAuthToken = await getToken();
to chrome localstorage.
Then in the background/content i just get the auth token from localstorage.
But ideally there would be another way provided by Clerk.
Yes, I agree. Thank you for the reply @jellohouse!
Isn't the issue with this that the token expires and there is no clean way to refresh it?
I have the same use case of needing auth in the background script.
Here is my flow:
Hi, thanks for the issue!
We're not actively monitoring issues in starter repositories and as such I'd recommend asking your question either in GitHub Discussions or on our Discord server.
Thanks!
Agreed @zacharyblank . This is actually what i've tried to do now: Start the clerk instance from the background script.
Then in the popup I wanted to use <ClerkProvider Clerk={clerk} navigate={(to) => navigate(to)}> .... </ClerkProvider>
where clerk is the instance from the background script. However, I'm getting an error from clerkjs that window is undefined from the background script.
And yes, now I realized that I am facing this issue with my previous attempt/solution, the auth token is only valid for about a minute and then it stops working.
Still looking for a solution... open to any suggestions.
I got this working with the following approach:
window.postMessage({
isSignedIn: true
})
window.addEventListener("message", async (event) => {
if (event.data.isSignedIn) {
const response = await sendToBackground({
name: "set-session",
body: document.cookie
})
}
})
I hope this helps!
Ok i see when i do console.log(document.cookie)
from the content script, there is a cookie called __clerk_db_jwt
Assuming i have that cookie value in my content/background scripts, how would i get a clerk auth token for the user logged in to my extension popup?
Is there a way to start a new clerk instance with that cookie and get the user auth token? Or any way to start clerk in the background with a session from the popup?
P.S. I don't have a website and i would like to avoid it if possible...
You can likely get away with the same pattern without a hosted site of your own if you want to use chrome pages (hosted by the browser itself and packaged with your extension).
instead of __clerk_db_jwt
look at the __session
cookie. Once you have that you can create any number of tokens for any jwt templates you want using the Clerk Backend API. This is what I do. Store the session ID in the background service and then generate a new token whenever one is needed and pass that new token to the content script.
This is part of a Clerk backend interface that I wrote that handles creating new tokens. It isn't perfect but hopefully gives you an idea:
import type { Clerk } from "./clerk"
import jwt from "jsonwebtoken"
export class Session {
clerk: Clerk
constructor(clerk: Clerk) {
this.clerk = clerk
}
async getToken(template: string): Promise<{ jwt: string }> {
var id: string
try {
id = (
(await this.clerk.storage.get("session")) as {
sid: string
}
).sid
} catch (e) {
console.error("Invalid or no session found in local storage")
}
// check if there is an existing token first
var token = await this.clerk.storage.get(`${template}_token`)
if (token) {
const decoded = jwt.decode(token)
if (decoded.exp) {
const currentTimestamp = Math.floor(Date.now() / 1000) // Convert milliseconds to seconds
if (decoded.exp > currentTimestamp) {
return { jwt: token }
}
} else {
return { jwt: token }
}
}
var { jwt: token } = (await this.clerk._makeRequest(
`/sessions/${id}/tokens/${template}`,
{},
"POST"
)) as { jwt: string }
await this.clerk.storage.set(`${template}_token`, token)
return { jwt: token }
}
async revoke(id: string) {
this.clerk.storage.clear()
return await this.clerk._makeRequest(`/sessions/${id}/revoke`, {}, "POST")
}
async get(id: string) {
return await this.clerk._makeRequest(`/sessions/${id}`, {}, "GET")
}
}
I am interested to know if you get it working!
Ok so i would need to call this endpoint https://api.clerk.com/v1/sessions/{session_id}/verify
Described here https://clerk.com/docs/reference/backend-api/tag/Sessions#operation/VerifySession
I tried setting the session ID in path and body token
to the value of __session
from the popup.
But i see the endpoint requires an auth token in headers. I tried setting auth as the __clerk_db_jwt
but that didn't work...
I'm getting error 401 unauthorized.
How do i get the Bearer auth token for the request?
Sorry for the delayed response. Call the Clerk Backend API with your clerk api token. Not the user's auth token :)
Please do not include your secret key in your chrome extension's source code!!
Publishable key: This key should be used in your frontend code, can be safely shared, and does not need to be kept secret. Secret key: These are the secret keys to be used from your backend code. They are sensitive and should be deleted if leaked.
Chrome extensions entire source is available to the browser, allowing anyone to view the source and steal your client secret.
The proper way to accomplish this in chrome extensions, native apps, mobile apps, SPA's etc where a client secret cannot be securely stored is using PKCE flow.
It looks like Clerk does support PCKE now, but have not tried this myself. https://clerk.com/docs/advanced-usage/clerk-idp
In my extension Popup i have the
<ClerkProvider>
component wrapping the app.I'm able to login and use all the hooks from the popup and components in the popup.
But now i want to access the logged in user session from my content script and background script.
How can i achieve this?