The createClerkClient() helper initializes a new Clerk instance on demand and refreshes the session token if there is a valid, signed-in user. It can be used in a background service worker to access a user's information or session token.
When a side panel or a popup is closed, the Clerk process that normally refreshes the user's session token every 60 seconds is no longer running, and the stored session will become stale. If a request were made 60 seconds after the side panel or popup was closed, it would fail because the session token is no longer valid. By configuring createClerkClient() to run in a background service worker, you can ensure that the user's session is always fresh.
Creates a background service worker that sets up an event listener to handle requests from a content script. If the request wants to interact with Clerk, the listener calls createClerkClient() to create a Clerk instance and refresh the session token, and then calls getToken()JavaScript Icon to get the token.
Adds a link to the home page of the extension that when visited, opens the page as a new tab.
The new tab has a button on it that, when clicked, triggers the background service worker.
In the src/ directory, create the background/ directory.
In the background/ directory, create the index.ts file.
In the index.ts file, paste the following code to create an event listener that listens for messages from content scripts and calls a function that uses createClerkClient() to get a new token for the user.
src/background/index.ts
import { createClerkClient } from'@clerk/chrome-extension/background'constpublishableKey=process.env.PLASMO_PUBLIC_CLERK_PUBLISHABLE_KEYif (!publishableKey) {thrownewError('Please add the PLASMO_PUBLIC_CLERK_PUBLISHABLE_KEY to the .env.development file')}// Use `createClerkClient()` to create a new Clerk instance// and use `getToken()` to get a fresh token for the userasyncfunctiongetToken() {constclerk=awaitcreateClerkClient({ publishableKey, })// If there is no valid session, then return null. Otherwise proceed.if (!clerk.session) {returnnull }// Return the user's sessionreturnawaitclerk.session?.getToken()}// Create a listener to listen for messages from content scripts// It must return true, in order to keep the connection open and send a response later.// NOTE: A runtime listener cannot be async.chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {// This example sends the token back to the content script// but you could also use the token to perform actions on behalf of the usergetToken().then((token) =>sendResponse({ token })).catch((error) => {console.error('[Background service worker] Error:',JSON.stringify(error))// If there is no token then send a null responsesendResponse({ token:null }) })returntrue// REQUIRED: Indicates that the listener responds asynchronously.})
In the src/ directory, create the tabs/ directory.
In the tabs/ directory, create the background-worker-demo.html file.
In the background-worker-demo.html file, paste the following code to create a basic HTML file that will house the React component for the content script.
src/tabs/background-worker-demo.html
In the tabs/ directory, create the background-worker-demo.tsx file.
In the background-worker-demo.tsx file, paste the following code to create a React component with a button that will trigger the background service worker to get the token. If the token is returned, it will be displayed on the page.
src/tabs/background-worker-demo.tsx
import*as React from'react'exportdefaultfunctionNewTab() {const [token,setToken] =React.useState<string|null>(null)constgetToken=async (e:React.MouseEvent<HTMLButtonElement>) => {e.preventDefault()// Trigger the background service worker to get the token// and set the token in the statechrome.runtime.sendMessage({ greeting:'get-token' }, (response) => {setToken(response.token) }) }return ( <div> <p>Clerk Background Worker Demo</p> <divclassName="App"> <p> This new tab simulates a content page where you might want to access user information, or make a request to your backend server and include a user token in the request. </p> <p>Make sure that you are signed into the extension. You can have the popup closed.</p> <buttontype="button"onClick={getToken} className="button invert"> Get token from service worker </button> {token && <p>Token: {token}</p>} </div> </div> )}
Add a button to your Chrome Extension to open the page you created in the previous step as a new tab. This can be added anywhere in your extension. The following example places the button on the home page of the extension.
src/popup/routes/home.tsx
exportconstHome= () => {return ( <> <h1>Clerk + Chrome Extension</h1> <buttononClick={() => {chrome.tabs.create({ url:'./tabs/background-worker-demo.html', }) }} > Open background worker demo in a new tab </button> </> )}