Skip to content

Verify Access Tokens

Use this page when your backend receives a SigID access token and needs to decide whether to trust it.

Do not trust frontend session state by itself. The backend must validate tokens before serving protected resources.

What A Token Does

A SigID access token is a signed statement that says who or what is calling your API, who issued the token, which API it is meant for, which workspace or tenant it belongs to, when it expires, and which scopes it carries.

Your backend should use those claims to make authorization decisions.

Required Checks

Check Why it matters
Signature Proves the token was issued by the expected SigID issuer.
Issuer Rejects tokens from another environment or identity surface.
Audience Rejects tokens meant for a different API.
Expiry Rejects expired tokens.
Tenant or workspace Keeps customer or workspace data isolated.
Scopes Enforces least-privilege API access.
Subject type Distinguishes humans, organizations, agents, or delegated subjects where relevant.

Tenant binding is opt-in

The SDK's tenantId option is optional, and the tenant check is skipped entirely when it is omitted: no wrong_tenant error fires and a token issued for any tenant is accepted. Single-tenant resource servers must always pass tenantId. Multi-tenant resource servers (one deployment serving many tenants) cannot pin a single value, so they must scope every data lookup by the validated claims.tenantId and never trust a tenant ID supplied by the client.

Next.js Helper

Use requireAccessToken() for protected Next.js route handlers:

import { accessTokenErrorResponse, requireAccessToken } from "@sigid/next";

export async function GET(request: Request) {
  try {
    const claims = await requireAccessToken(request, {
      issuer: process.env.NEXT_PUBLIC_SIGID_ISSUER_URL!,
      audience: process.env.SIGID_API_AUDIENCE!,
      tenantId: process.env.SIGID_TENANT_ID!,
      scopes: ["projects:read"],
      allowedSubjectTypes: ["human"],
    });

    return Response.json({ ok: true, subject: claims.subject });
  } catch (error) {
    return accessTokenErrorResponse(error);
  }
}

Common Mistakes

  • accepting a token without checking aud
  • checking signature but not tenant or workspace context
  • decoding JWTs without validation
  • accepting frontend-provided user IDs instead of token claims
  • treating ID tokens as API authorization tokens
  • using development issuer settings in production

After token validation works, continue to Protect Backend APIs.

For claim details, read Reference: Claims And Scopes.