Token claims
Every claim Whisp3r Auth emits in id_token and /oauth2/userinfo responses. Absent claims mean
"not consented" — not null.
Always present
- sub
- The pairwise subject identifier — unique to your
client_id. Stable across sessions for your app. Use as your users-table primary key. - iss
- Issuer. Always matches the discovery document's
issuerfield. Verify on everyid_token. - aud
- Your
client_id. Verify on everyid_token. - iat / exp
- Issued-at / expires-at, seconds since epoch.
id_token-only claims
- amr
- Authentication Methods References, per OIDC Core 5.1. Present as
["mfa", "otp"]when the user passed 2FA on this session. Absent when the user signed in with a single factor — that's the OIDC convention for "single-factor." Read this for runtime auth-strength decisions even if you don't require 2FA at sign-in. - nonce
- Echoes the
nonceyou sent in the authorize request. Verify it matches.
Scope-gated claims
- picture
wa:photo— the avatar URL when one is uploaded, null when not. Consumers must render a fallback (initials, gradient, default mark) for the null case; Whisp3r Auth does NOT ship a deterministic generated avatar.- given_name
wa:name.first(orwa:name.full)- name, middle_name, family_name, suffix
wa:name.full— the composed display name plus every component, so consumers can render the joined string or pull just the family name without re-requesting.- preferred_username
wa:username- pronouns
wa:pronouns- age_at_least_13, age_at_least_16, age_at_least_18, age_at_least_21
wa:age.tiers— boolean per tier. Auth never exposes the underlying birthday under this scope; consumers only see yes/no thresholds.- age_verification
wa:age.tiers— companion to the tier booleans. Object shape:{ verified, method, verified_at }. Returns{ verified: false, method: null, verified_at: null }today; flips toverified: trueafter the user completes an ID-document verification flow (Persona, Stripe Identity, etc. — not yet wired). Gate sensitive features onage_verification.verified === trueif you need an attested age, not a self-reported one.- birthdate
wa:birthday— ISOYYYY-MM-DD, self-reported.- birthdate_verification
wa:birthday— same shape asage_verification. Flips when the verified ID document's birthday matches the stored value.- locale
wa:language— BCP-47 tag- cookie_preferences
wa:cookies— object withanalytics+marketingbooleans- profile_alias
- Any of
wa:name.first,wa:name.full,wa:username,wa:pronouns,wa:language— directory alias, e.g."profile@nick" - picture_alias
wa:photo— directory alias, e.g."avatar@nick"- directory
- Issued whenever
profile_aliasorpicture_aliasis — base URL of the directory resolver, e.g."https://auth.whisp3r.com"
The three directory claims let your app resolve a signed,
cache-friendly canonical body via GET /v1/c/<alias> instead of duplicating
identity fields into your database. They're issued automatically
alongside the field scopes that back them — no separate scope to
request. See Identity directory for the full contract.
Signature verification
Every id_token is signed EdDSA. Fetch the JWKS from the jwks_uri in discovery, find the key matching the token's kid header, and verify the signature. Then check:
issmatches the issuer from discoveryaudmatches yourclient_idexpis in the futureiatis not too far in the past (5-minute leeway is standard)noncematches what you sent
If any of those fail, reject the token. Most OIDC libraries do all of this automatically; if you're hand-rolling, do not skip a single check.