Verify tokens

Verify that a caller is still trusted — online through Cliodot, or offline for cryptography-only checks.

Cliodot re-checks signature, expiry, revocation, and trust:

TypeScript
const verified = await identity.verify({
  access_token: tokens.access_token,
});

const bound = await identity.verify({
  access_token: tokens.access_token,
  target_app_id: "identity_hrms",
});

const scoped = await identity.verify({
  access_token: tokens.access_token,
  required_scopes: ["employees.read"],
});

required_scopes requires the scopes license; missing scopes → IDENTITY_SCOPE_INSUFFICIENT. Maps to POST /identity/v1/verify or POST /identity/v1/apps/:appId/verify.


Offline checks cryptography and exp only — not trust or revocation. Prefer online verify() when those matter.

HS256#

TypeScript
import { verifyIdentityTokenOffline } from "cliodot";

const claims = await verifyIdentityTokenOffline(tokens.access_token, {
  algorithm: "HS256",
  secret: process.env.HRMS_JWT_VERIFY_SECRET!,
});

RS256 (JWKS)#

TypeScript
const claims = await verifyIdentityTokenOffline(tokens.access_token, {
  algorithm: "RS256",
  jwksUrl: "https://your-host/identity/v1/apps/identity_hrms/jwks.json",
});

Or pass publicKeyPem directly. JWKS responses are cached (default 5 minutes); a missing kid triggers one refresh.

Scope checks offline#

TypeScript
import { tokenHasScopes, parseIdentityScopeClaim } from "cliodot";

const ok = tokenHasScopes(tokens.access_token, ["employees.read"]);
const scopes = parseIdentityScopeClaim(claims);

Offline scope checks are local only; they do not re-check trust or Cliodot grants.

Token cache helper#

TypeScript
import { createIdentityTokenCache } from "cliodot";

const cache = createIdentityTokenCache({ client: identity });
const accessToken = await cache.getAccessToken("identity_hrms");

Authenticates on miss; refreshes when a refresh token is available; clears near expiry with a skew window.