Cliodot re-checks signature, expiry, revocation, and trust:
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#
import { verifyIdentityTokenOffline } from "cliodot";
const claims = await verifyIdentityTokenOffline(tokens.access_token, {
algorithm: "HS256",
secret: process.env.HRMS_JWT_VERIFY_SECRET!,
});RS256 (JWKS)#
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#
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#
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.