Skip to main content

Custom JWT Integration

If you already have an authentication system that issues JWTs (Auth0, Firebase Auth, Supabase Auth, Clerk, or a custom backend), you can use the custom_jwt auth method to connect it to Privacy Boost. Your backend validates the user’s identity with your auth provider and forwards a JWT to Privacy Boost, which verifies it via your JWKS endpoint.

How It Works

Custom JWT Authentication Flow

Server-Side Setup

Your app must be configured with the custom_jwt auth method. Contact the Privacy Boost team with:
  • JWKS URL — The HTTPS endpoint serving your JSON Web Key Set (e.g., https://your-auth.com/.well-known/jwks.json). Privacy Boost fetches this to verify JWT signatures.
  • Audience (optional) — Expected aud claim in your JWTs. If set, only tokens with a matching audience are accepted.
  • Issuer (optional) — Expected iss claim in your JWTs. If set, only tokens with a matching issuer are accepted.
The backend configuration looks like:
{
  "jwks_url": "https://your-auth.com/.well-known/jwks.json",
  "audience": "your-app-id",
  "issuer": "https://your-auth.com"
}

JWT Requirements

Your JWT must:
  • Be signed with RS256, RS384, RS512, ES256, ES384, or ES512
  • Include a kid (Key ID) header matching a key in your JWKS
  • Include a sub or user_id claim identifying the user
  • Match the configured aud and iss (if set)
  • Be valid (not expired)

Client-Side Integration

1. Implement a Token Provider

Your token provider routes the SDK’s login payload through your backend, which attaches the custom JWT:
const tokenProvider = async (loginPayload: any) => {
  // Get your auth token (from your auth system)
  const yourAuthToken = await getYourAuthToken();

  // Send both to your backend
  const res = await fetch('https://your-backend.com/api/privacy-boost/auth', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${yourAuthToken}`,
    },
    body: JSON.stringify(loginPayload),
  });

  return await res.json(); // { token, expiresIn }
};

2. Pass the Token Provider to authenticate()

await sdk.auth.authenticate(adapter, {
  type: 'walletDerived',
  tokenProvider,
});

3. Implement the Backend Endpoint

Your backend endpoint receives the SDK’s login payload, attaches your JWT, and forwards to Privacy Boost:
// Express.js example
app.post('/api/privacy-boost/auth', async (req, res) => {
  // 1. Verify your own auth (e.g., check the Authorization header)
  const user = await verifyYourAuth(req.headers.authorization);
  if (!user) return res.status(401).json({ error: 'Unauthorized' });

  // 2. Get a JWT for this user from your auth system
  const customJWT = await issueJWTForUser(user.id);

  // 3. Forward to Privacy Boost with the custom JWT attached
  const pbResponse = await fetch('https://test-api.privacy-boost.sunnyside.io/indexer/auth/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      ...req.body,            // SDK's login payload (mpk, viewauth_signature, nonce, etc.)
      custom_jwt_token: customJWT,  // Your JWT
    }),
  });

  const data = await pbResponse.json();
  res.json({
    token: data.access_token,
    expiresIn: data.expires_in,
  });
});

Testing

For development, you can use app_id_only to skip the token provider entirely. Switch to custom_jwt when moving to production.

Next Steps

Continue with setup: Or explore other auth methods:
  • Privy — For Privy social login and embedded wallets
  • Dynamic — For Dynamic wallet connection and embedded wallets
  • API Secret — For server-to-server with client credentials