Skip to main content
The @revstackhq/auth package provides a unified JWT verification system that works with multiple authentication providers. It handles both RS256 (public key) and HS256 (shared secret) signing strategies.

TokenVerifier

The TokenVerifier class validates JWT tokens against a stored authentication contract.

Constructor

new TokenVerifier(contract: RevstackAuthContract, options?: TokenVerifierOptions)
contract
RevstackAuthContract
required
The authentication contract defining verification parameters (strategy, JWKS URI, issuer, etc.)
options
TokenVerifierOptions
Optional configuration for JWKS caching and timeouts

TokenVerifierOptions

jwksCache
RemoteJWKSetOptions
Options passed to the underlying jose library’s createRemoteJWKSet for cache control and timeouts

Methods

verify

Validates a raw JWT string and returns a session object with user claims.
async verify<T extends Record<string, unknown>>(
  token: string
): Promise<RevstackSession<T>>
token
string
required
The JWT token string to verify
Returns: Promise<RevstackSession<T>> - Session object containing user ID, claims, and validation status
import { TokenVerifier } from "@revstackhq/auth";

const verifier = new TokenVerifier({
  provider: "clerk",
  strategy: "RS256",
  jwksUri: "https://clerk.your-domain.com/.well-known/jwks.json",
  issuer: "https://clerk.your-domain.com",
});

const session = await verifier.verify(token);

if (session.isValid) {
  console.log("User ID:", session.userId);
  console.log("Claims:", session.claims);
} else {
  console.error("Error:", session.error);
  console.error("Error Code:", session.errorCode);
}

Types

RevstackSession

The session object returned by verify():
userId
string
required
The authenticated user ID extracted from the token (from sub or custom claim)
claims
T extends Record<string, unknown>
required
The raw decoded JWT payload containing all token claims
isValid
boolean
required
Whether the token passed validation. Check this before trusting userId or claims
error
string
Human-readable error message if isValid is false
errorCode
AuthErrorCode
Specific error code if isValid is false. See Error Codes

RevstackAuthContract

Union type representing either RS256 or HS256 authentication configuration.

RS256AuthContract

Used for providers like Auth0, Clerk, Firebase that use public key cryptography:
provider
AuthProviderSlug
required
Provider identifier: "auth0" | "clerk" | "supabase" | "cognito" | "firebase" | "custom"
strategy
'RS256'
required
Discriminator for RS256 verification via remote JWKS
jwksUri
string
required
The JSON Web Key Set URI to verify signatures (e.g., https://your-domain.auth0.com/.well-known/jwks.json)
issuer
string
required
Expected issuer (iss) claim value
audience
string
Expected audience (aud) claim value
userIdClaim
string
Claim holding the unique user ID. Defaults to "sub" if not specified

HS256AuthContract

Used for custom JWTs or providers that support shared secrets:
provider
AuthProviderSlug
required
Provider identifier: "auth0" | "clerk" | "supabase" | "cognito" | "firebase" | "custom"
strategy
'HS256'
required
Discriminator for HS256 verification via shared secret
signingSecret
string
required
Shared signing secret used to verify signatures
issuer
string
Expected issuer (iss) claim, if enforced
audience
string
Expected audience (aud) claim, if enforced
userIdClaim
string
Claim holding the unique user ID. Defaults to "sub" if not specified

Error Codes

TOKEN_EXPIRED
AuthErrorCode
The token has expired (based on exp claim)
INVALID_SIGNATURE
AuthErrorCode
The token signature verification failed
ISSUER_MISMATCH
AuthErrorCode
The iss claim doesn’t match the expected issuer
NETWORK_ERROR
AuthErrorCode
Failed to fetch JWKS from the remote endpoint (RS256 only)
MISSING_CLAIM
AuthErrorCode
The required user ID claim is missing from the token
INVALID_FORMAT
AuthErrorCode
The token has malformed JWT structure or failed claim validation
UNKNOWN_ERROR
AuthErrorCode
An unexpected error occurred during verification

Provider Input Types

Helper types for creating auth contracts for specific providers:

Auth0Input

domain
string
required
Auth0 domain, with or without protocol (e.g., "my-tenant.us.auth0.com")
audience
string
Expected audience (aud)
userIdClaim
string
Optional override for user ID claim

ClerkInput

issuerUrl
string
required
Clerk issuer URL (e.g., "https://clerk.your-domain.com")
userIdClaim
string
Optional override for user ID claim

SupabaseInput

projectUrl
string
required
Supabase project URL (e.g., "https://xyzcompany.supabase.co")
signingSecret
string
Optional JWT signing secret for HS256 verification. If provided, the contract becomes HS256
audience
string
Optional expected audience (aud)
userIdClaim
string
Optional override for user ID claim

FirebaseInput

projectId
string
required
Firebase project ID (e.g., "my-firebase-project")
userIdClaim
string
Optional override for user ID claim

CognitoInput

region
string
required
AWS region (e.g., "us-east-1")
userPoolId
string
required
Cognito User Pool ID (e.g., "us-east-1_Abc123")
clientId
string
Cognito App Client ID (used as aud)
userIdClaim
string
Optional override for user ID claim

CustomJwtInput

signingSecret
string
required
HS256 signing secret
issuer
string
Optional expected issuer (iss)
audience
string
Optional expected audience (aud)
userIdClaim
string
Optional override for user ID claim

Example Usage

Auth0 Integration

import { TokenVerifier } from "@revstackhq/auth";

const verifier = new TokenVerifier({
  provider: "auth0",
  strategy: "RS256",
  jwksUri: "https://my-tenant.auth0.com/.well-known/jwks.json",
  issuer: "https://my-tenant.auth0.com/",
  audience: "https://my-api.com",
});

const session = await verifier.verify(authToken);

Supabase with HS256

import { TokenVerifier } from "@revstackhq/auth";

const verifier = new TokenVerifier({
  provider: "supabase",
  strategy: "HS256",
  signingSecret: process.env.SUPABASE_JWT_SECRET,
  issuer: "https://xyzcompany.supabase.co/auth/v1",
});

const session = await verifier.verify(token);

Error Handling

const session = await verifier.verify(token);

if (!session.isValid) {
  switch (session.errorCode) {
    case "TOKEN_EXPIRED":
      return res.status(401).json({ error: "Token expired. Please log in again." });
    case "INVALID_SIGNATURE":
      return res.status(401).json({ error: "Invalid token signature." });
    case "ISSUER_MISMATCH":
      return res.status(401).json({ error: "Token from untrusted issuer." });
    default:
      return res.status(401).json({ error: session.error });
  }
}

// Token is valid, proceed with request
const userId = session.userId;

Best Practices

Cache TokenVerifier instances: Create one verifier per auth provider and reuse it across requests. The JWKS cache is managed internally.
Validate isValid before trusting data: Always check session.isValid before using userId or claims. Invalid tokens will still return a session object with isValid: false.
Custom claims: Access custom claims via session.claims. For example, if your tokens include a role claim: const role = session.claims.role;

Build docs developers (and LLMs) love