Skip to content

JWT Methods ​

Ready-made functions that satisfy the JwtVerify, JwtDecode, ClientAssertionJwtVerify, JwkVerify, and JwkThumbprintCalculator interfaces expected by @saurbit/oauth2. They wrap jose and handle the necessary type conversions so you can plug them directly into the @saurbit/oauth2 builders.

verifyJwt ​

ts
const verifyJwt: JwtVerify

Verifies a JWT using the provided secret or key and returns the decoded payload. Wraps jose's jwtVerify.

TIP

For verifying client assertion JWTs in ClientSecretJwt or PrivateKeyJwt, use verifyClientAssertionJwt or createClientAssertionJwtVerify instead — they accept the richer ClientAssertionJwtVerify signature and allow to enforce the claims required by RFC 7523.


createJwtVerify ​

Creates a JwtVerify function with pre-configured claim verification options (issuer, audience, etc.). This is useful when you want to reuse the same verification settings across multiple calls without repeating them each time.

ts
function createJwtVerify(options: JwtClaimVerificationOptions): JwtVerify

TIP

For pre-configuring verification options when using ClientSecretJwt or PrivateKeyJwt, use createClientAssertionJwtVerify instead — it accepts the full ClientAssertionJwtContext and Request for more context-aware verification.


verifyClientAssertionJwt ​

ts
const verifyClientAssertionJwt: ClientAssertionJwtVerify

Verifies a client assertion JWT using the provided secret or key and returns the decoded payload. Wraps jose's jwtVerify and allows to enforce issuer and subject equal to clientId as required by RFC 7523.

Pass this as the ClientAssertionJwtVerify argument to ClientSecretJwt or PrivateKeyJwt.

Usage with ClientSecretJwt ​

ts
import { ClientSecretJwt } from "@saurbit/oauth2";
import { decodeJwt, verifyClientAssertionJwt } from "@saurbit/oauth2-jwt";

const clientSecretJwt = new ClientSecretJwt(decodeJwt, verifyClientAssertionJwt)
  .addAlgorithm(ClientSecretJwt.algo.HS256)
  .getClientSecret(async (clientId) => {
    const client = await db.findClientById(clientId);
    return client?.secret ?? null;
  });

Usage with PrivateKeyJwt ​

ts
import { PrivateKeyJwt } from "@saurbit/oauth2";
import { decodeJwt, verifyClientAssertionJwt } from "@saurbit/oauth2-jwt";

const privateKeyJwt = new PrivateKeyJwt(decodeJwt, verifyClientAssertionJwt)
  .addAlgorithm(PrivateKeyJwt.algo.RS256)
  .getPublicKeyForClient(async (clientId) => {
    const client = await db.findClientById(clientId);
    return client?.publicKey ?? null;
  });

createClientAssertionJwtVerify ​

Creates a ClientAssertionJwtVerify function with pre-configured claim verification options. Useful when you need to enforce additional claims (e.g. audience) beyond the default iss/sub enforcement, or when verification options depend on the request context.

ts
// Static options
function createClientAssertionJwtVerify(
  options: JwtClaimVerificationOptions,
): ClientAssertionJwtVerify;

// Dynamic options from context
function createClientAssertionJwtVerify(
  callback: (context: ClientAssertionJwtContext, request: Request, key: Uint8Array | object, options?: { algorithms?: string[] }) => JwtClaimVerificationOptions | Promise<JwtClaimVerificationOptions>,
): ClientAssertionJwtVerify;

Usage with static options ​

ts
import { ClientSecretJwt } from "@saurbit/oauth2";
import { createClientAssertionJwtVerify, decodeJwt } from "@saurbit/oauth2-jwt";

const verifyClientAssertion = createClientAssertionJwtVerify({
  audience: "https://auth.example.com/token",
});

const clientSecretJwt = new ClientSecretJwt(decodeJwt, verifyClientAssertion)
  .addAlgorithm(ClientSecretJwt.algo.HS256)
  .getClientSecret(async (clientId) => {
    const client = await db.findClientById(clientId);
    return client?.secret ?? null;
  });

Usage with dynamic options ​

ts
import { PrivateKeyJwt } from "@saurbit/oauth2";
import { createClientAssertionJwtVerify, decodeJwt } from "@saurbit/oauth2-jwt";

const verifyClientAssertion = createClientAssertionJwtVerify(
  async (context, request) => {
    const url = new URL(request.url);
    return {
      audience: url.origin + url.pathname,
      issuer: context.clientId,
    };
  },
);

const privateKeyJwt = new PrivateKeyJwt(decodeJwt, verifyClientAssertion)
  .addAlgorithm(PrivateKeyJwt.algo.ES256)
  .getPublicKeyForClient(async (clientId) => {
    const client = await db.findClientById(clientId);
    return client?.publicKey ?? null;
  });

decodeJwt ​

ts
const decodeJwt: JwtDecode

Decodes a JWT payload without verifying its signature. Wraps jose's decodeJwt.

Pass this as the JwtDecode argument to ClientSecretJwt or PrivateKeyJwt alongside verifyClientAssertionJwt.

WARNING

This function does not validate the token's signature, expiration, or any other claims. Use it only to inspect the token payload before verification, as done internally by ClientSecretJwt and PrivateKeyJwt to extract the client_id from the assertion.


verifyJwk ​

ts
const verifyJwk: JwkVerify

Verifies a JWT whose header embeds the public key as a JWK ("jwk" header parameter). The public key is extracted from the JWT header itself and used to verify the signature. Only the ES256, ES384, ES512, PS256, PS384, and PS512 algorithms are accepted.

Pass this as the JwkVerify argument to DPoPTokenType.

Usage with DPoPTokenType ​

ts
import { createInMemoryReplayStore, DPoPTokenType } from "@saurbit/oauth2";
import { calculateJwkThumbprint, verifyJwk } from "@saurbit/oauth2-jwt";

const dpop = new DPoPTokenType(verifyJwk, calculateJwkThumbprint, createInMemoryReplayStore());

Then pass it to your flow builder:

ts
import { AuthorizationCodeFlowBuilder } from "@saurbit/oauth2";

const flow = new AuthorizationCodeFlowBuilder({ tokenEndpoint: "/token" })
  .setTokenType(dpop)
  // ... other builder methods
  .build();

createDPoPJwkVerify ​

Creates a JwkVerify function with a custom set of allowed algorithms. This is useful if you want to restrict the algorithms accepted for DPoP token validation.

ts
const createDPoPJwkVerify: (config?: DPoPJwkVerifierConfig) => JwkVerify

Usage with DPoPTokenType ​

ts
import { createInMemoryReplayStore, DPoPTokenType } from "@saurbit/oauth2";
import { calculateJwkThumbprint, createDPoPJwkVerify } from "@saurbit/oauth2-jwt";

const dpop = new DPoPTokenType(
  createDPoPJwkVerify(["ES256", "PS256"]), 
  calculateJwkThumbprint, 
  createInMemoryReplayStore()
);

calculateJwkThumbprint ​

ts
const calculateJwkThumbprint: JwkThumbprintCalculator

Calculates the SHA-256 JWK thumbprint for a given JSON Web Key. The result is a base64url-encoded string that uniquely identifies the key. Wraps jose's calculateJwkThumbprint.

Pass this as the JwkThumbprintCalculator argument to DPoPTokenType.

Usage in an Authorization Code Flow ​

ts
import { AuthorizationCodeFlowBuilder, DPoPTokenType, createInMemoryReplayStore,  } from "@saurbit/oauth2";
import { JoseJwksAuthority, calculateJwkThumbprint, createInMemoryKeyStore, verifyJwk } from "@saurbit/oauth2-jwt";

// key store and authority
const jwksAuthority = new JoseJwksAuthority(createInMemoryKeyStore(), 8.64e6);

// token type
const dpop = new DPoPTokenType(verifyJwk, calculateJwkThumbprint, createInMemoryReplayStore());

// flow builder
const flow = new AuthorizationCodeFlowBuilder({ tokenEndpoint: "/token" })
  // set the DPoP token type for the flow
  .setTokenType(dpop)
  // handle token verification
  .verifyToken(async (_, { token, tokenTypeValidation }) => {
    
    // verify the JWT and extract its payload
    const jwtAccessTokenPayload = await jwksAuthority.verify(token);
    
    try {
      // validate the DPoP proof and its thumbprint
      dpop.validateThumbprint(tokenTypeValidation, jwtAccessTokenPayload);
    } catch (error) {
      // If the DPoP proof is invalid or the thumbprint does not match, return an invalid token response.
      return { isValid: false, message: error.message };
    }

    // ... additional validation logic ...
  })
  // ... other builder methods
  .build();