Hanko Custom Claims Guide:About Hanko:Hanko is a modern open source authentication solution and the fastest way you integrate passkeys, 2FA, SSO, and more—with full control over your data. Move between self-hosted and Hanko Cloud anytime. No lock-in. Just Auth how it should be: secure, user friendly, and fully yours.What This Guide Covers: This guide explains Hanko’s custom claims: declaring a project-wide set of typed claims,
mapping them from enterprise and social (OIDC/OAuth) connections, and where resolved values become available
(session JWTs, the Admin API).Prerequisites:
Custom claims let you declare your own project-wide set of typed claims and have enterprise or social (OIDC/OAuth)
connections map their own attributes/claims onto them. This is distinct from
attribute mapping, which renames a provider attribute/claim into one of
Hanko’s fixed standard slots (name, email, …) - custom claims are project-defined, not fixed, and none of them
are added to the session JWT automatically (see Accessing custom claims for how to opt one
in).
- Active Hanko project
- At least one enterprise or custom OIDC/OAuth connection configured
- Declare a custom claim
- Map a custom claim on an enterprise connection
- Map a custom claim on a social (OIDC/OAuth) connection
- Understand how resolved values are stored and cleared
- Access a resolved claim from a JWT template or the Admin API
Declaring custom claims
To declare a custom claim:- Log in to Hanko Cloud and select your project.
- Navigate to
Settings > Custom claims. - Click
New claim. - Provide a
Name, aType(string,number,boolean, orstring_list), and an optionalDescription. - Click
Save.
sub, iat, exp, aud, iss, email, username,
session_id).
Custom claims are deliberately scalar or list-of-scalar only (string, number, boolean, string_list) - there’s
no nested/object type. Enterprise connection attributes are structurally flat, and this keeps one claim shape across
both connection types.
Mapping custom claims
Once declared, an enterprise or social connection can map its own attributes/claims onto your custom claims. A mapping that references a claim name you haven’t declared is rejected - this is checked both when you save the mapping and whenever you remove a claim definition a connection still maps.Enterprise connections
- Log in to Hanko Cloud and select your project.
- Navigate to
Settings > Enterprise connectionsand open (or create) a connection. - Under
Custom claims, add a mapping from each claim name to the SAML attribute name that should populate it. - Click
Save.
Social connections
Custom claim mapping is available for custom OAuth/OIDC providers you’ve configured yourself - not the built-in providers (Apple, Discord, GitHub, Google, LinkedIn, Microsoft).- Log in to Hanko Cloud and select your project.
- Navigate to
Settings > Social connectionsand open (or create) a custom provider. - Under
Custom claim mapping, add a mapping from each claim name to the provider claim that should populate it. The provider claim may be a gjson path to reach into a nested claim. - Click
Save.
Each leaf field declared this way counts toward the 50-claim cap on its own. Flattening several nested objects
this way can approach that limit faster than declaring flat claims directly would.
string) is silently skipped rather than blocking sign-in - see
Resolving custom claims for exactly what happens to that claim’s stored value when this
occurs.
Resolving custom claims
Resolved custom claim values are stored per user, one per project. Whichever connection a user most recently authenticated with wins for any claim it maps (last-one-wins); if that connection no longer asserts a value for a claim it maps, the claim is cleared - but only if that same connection was the one that set it, so a connection can never clear a claim it doesn’t own. This is connection-type agnostic: if you map the same claim name on both an enterprise connection and a social connection, whichever one a user most recently signed in through owns it - there’s no separate precedence between connection types. A mapped value that fails to resolve to its claim’s declared type is treated differently from a genuinely absent value: it’s skipped without clearing whatever was previously stored, since a malformed value is evidence of a mapping problem, not evidence the claim no longer applies. Resolved values are visible on a user’s detail page underCustom claims, and via the read-only
Get custom claims of a user Admin API
endpoint.