accounts
Version:
Tempo Accounts SDK
47 lines • 2.22 kB
JavaScript
import { createRemoteJWKSet, jwtVerify } from 'jose';
/** Cache of remote JWKS sets keyed by issuer, so verification reuses fetched keys. */
const jwksCache = new Map();
/**
* Verifies an OIDC identity token (JWT) against an issuer's JWKS and returns its
* claims. Asserts the signature, `iss`, `aud`, and `exp` (via `jose`), plus
* `email_verified === true`. Optionally cross-checks `sub` (the account address)
* and `nonce` when provided. Throws on any failure.
*
* Standalone counterpart to `Handler.auth({ identity })` — use it when minting
* your own session inside `onAuthenticate` with `session: false`.
*/
export async function verify(idToken, options) {
const { audience, issuer, nonce, subject } = options;
let jwks = jwksCache.get(issuer);
if (!jwks) {
// Discover the JWKS endpoint (standard OIDC), falling back to the
// conventional path when the issuer omits the discovery document.
const discovery = await fetch(`${trimTrailingSlash(issuer)}/.well-known/openid-configuration`)
.then((res) => (res.ok ? res.json() : null))
.catch(() => null);
const jwksUri = discovery?.jwks_uri ?? `${trimTrailingSlash(issuer)}/.well-known/jwks.json`;
jwks = createRemoteJWKSet(new URL(jwksUri));
jwksCache.set(issuer, jwks);
}
const { payload } = await jwtVerify(idToken, jwks, {
algorithms: ['EdDSA'],
audience,
issuer,
});
if (payload.email_verified !== true)
throw new Error('email not verified');
if (subject && String(payload.sub).toLowerCase() !== subject.toLowerCase())
throw new Error('identity token subject mismatch');
if (nonce !== undefined && payload.nonce !== nonce)
throw new Error('identity token nonce mismatch');
return {
email: typeof payload.email === 'string' ? payload.email : undefined,
nonce: typeof payload.nonce === 'string' ? payload.nonce : undefined,
subject: String(payload.sub),
};
}
/** Strips a single trailing slash so issuer-relative URLs join cleanly. */
function trimTrailingSlash(value) {
return value.endsWith('/') ? value.slice(0, -1) : value;
}
//# sourceMappingURL=Identity.js.map