Skip to main content
For an SDK-agnostic explanation of JWTs and how verification works—applicable no matter which frontend SDK you use (React, Flutter, Swift, Kotlin, etc.)—see Server-side auth and JWT.

Option 1: Leverage NextAuth

If you are using Next.js, you can easily integrate the NextAuth library with Dynamic to perform server-side verification and then use a session client-side.

Option 2: Leverage Passport.js

We offer an official passport-dynamic extension.

Option 3: Do-It-Yourself Verification

  1. Get the JWT through the Dynamic SDK with an authToken.
  2. Send the authToken to the server as a Bearer token
React
import { useEffect, useState } from "react";

export const useFetch = (authToken: string | null) => {
  const [data, setData] = useState({});

  useEffect(() => {
    const fetchApi = async () => {
      await fetch("http://localhost:9000/api", {
        headers: {
          Authorization: `Bearer ${authToken}`,
        },
      }).then(response => response.json()).then(setData);
    }

    fetchApi()
  }, [authToken]);

  return { data };
};
  1. Install the node-jsonwebtoken and jwks-rsa packages
  2. Validate the JWT on your server by fetching the public key from the JWKS endpoint API endpoint and verifying the encoded JWT against the public key:
React
import jwt, { JwtPayload } from 'jsonwebtoken';
import { JwksClient } from 'jwks-rsa';

// can be found in https://app.dynamic.xyz/dashboard/developer/api
const jwksUrl = `https://app.dynamic.xyz/api/v0/sdk/${YOUR_DYNAMIC_ENV_ID}/.well-known/jwks`

// The client should be initialized as
const client = new JwksClient({
  jwksUri: jwksUrl,
  rateLimit: true,
  cache: true,
  cacheMaxEntries: 5,  // Maximum number of cached keys
  cacheMaxAge: 600000 // Cache duration in milliseconds (10 minutes in this case))}
 });

const signingKey = await client.getSigningKey();
const publicKey = signingKey.getPublicKey();

const decodedToken: JwtPayload = jwt.verify(encodedJwt, publicKey, {
  ignoreExpiration: false,
}) as JwtPayload;

if (decodedToken.scopes.includes('requiresAdditionalAuth')) {
  // Either reject or handle the scopes appropriately.
  // `requiresAdditionalAuth` is the scope used to indicate that JWT requires additional verification such as MFA.
  throw new Error('Additional verification required');
}

console.log(decodedToken) // { iss: 'xxxx', exp: nnnn, ... }
This uses the following libraries:
  • jwks-rsa: Provides client to interact and parse JWKS key signing data for a JWT.
  • jsonwebtoken: Provides library to encode/decode and validate a JWT token.