Rationale

Many apps don’t have their own dedicated backend and user management and rely on services like Clerk, Auth0, or Supabase to manage their users.

When you use Hyperspell’s SDK on a backend, you will use your secret API key to authenticate your app, and you can query a specific’s user data by simply passing the user’s ID.

However, if you mainly use a web or mobile application to query Hyperspell, we have to make sure that the user_id you pass in is actually the user_id of the user that is currently logged in — otherwise, a malicious user could query data from another user.

To prevent this, we can share a secret with Clerk that is only known to your app and not used in your frontend. Clerk will use that secret to cryptographically sign a JWT that you can pass in to your Hyperspell backend.

The Hyperspell backend will then be able to verify that JWT was signed with your app’s secret and extract the user’s ID from it.

Getting your JWT Secret and App ID

You can get your JWT secret and App ID from the Hyperspell dashboard on your app’s Api Keys page:

Setting up Clerk

  1. On the Clerk dashboard, go to your app’s settings and click on the “JWT Templates” tab in the left siderbar, right under “Session Management”.
  2. Click on “New Template”, and choose “Blank”.
  3. Name your template hyperspell.
  4. Enable the “Custom signing key” toggle.
  5. Choose “HS256” as the signing algorithm, and paste your JWT secret in the “Signing key” field.
  6. Paste the following payload in the “Claims” field, replacing YOUR_APP_ID with your app’s id:
{
    "ref": "YOUR_APP_ID"
}  
  1. Save your changes.

You’ll have to set up a JWT template for each environment (development, production) of your Clerk app. You can use the same public key and JWT secret for both.

Using the JWT in your app

First, we create a custom Hyperspell client that injects the Clerk Hyperspell token into the request headers. Clerk stores that token in the active session, so we will have to pass this session to our Hyperspell client.

Then, we use the useSession hook to get the Clerk session object and pass it to our Hyperspell client:

import Hyperspell from 'hyperspell';
import { ActiveSessionResource } from "@clerk/types";

export const HyperspellWithClerk = async (session: ActiveSessionResource | null | undefined) => {
    const clerkToken = await session?.getToken({
		// Pass the name of the JWT template you created in the Clerk Dashboard
		// For this tutorial, you named it 'hyperspell'
		template: 'hyperspell',
    })

    const client = new Hyperspell({ apiKey: clerkToken });
    return client;
}

If you’re using server-side components (for example, Next.js), you can just pass an API key to your Hyperspell client directly, as it will not be exposed to the client.