Everything Human Pass can put in an ID token, and what to ask for to get it.
Scopes
| Scope | Gives you | Notes |
|---|---|---|
openid | sub, and previous_sub after a rotation | Required |
personhood | verified_human, acr | Always ask for it |
age | age_over_21 | Optional attribute |
id_country | id_issuing_country | Optional attribute |
id_state | id_issuing_subdivision | Optional attribute; only with id_country |
There are no profile, email, phone or address scopes, by design.
Claims
| Claim | Type | Meaning |
|---|---|---|
sub | string | This person's ID in your project (up to 255 characters). More |
previous_sub | string | Only for a while after a rotation: the ID you knew before. More |
verified_human | boolean | Always true: the person verified a government ID with a live face match, and has no other Human Pass for it. |
acr | string | urn:humanpass:acr:id-verified-dedup |
age_over_21 | boolean | If agreed: 21 or over. |
id_issuing_country | string | If agreed: ISO 3166-1 alpha-2, e.g. US. |
id_issuing_subdivision | string | If agreed, with the country: ISO 3166-2, e.g. US-CA. |
The same claims are available from the UserInfo endpoint, but you don't need it: they're all in the ID token, which also carries the standard iss, aud, exp, iat, nonce and auth_time.
Example ID token
The decoded payload, for a project with the age attribute, after the person agreed:
json
{
"iss": "https://id.humanpass.co",
"aud": "hp_live_…",
"sub": "1.Ab3xQ9…",
"verified_human": true,
"acr": "urn:humanpass:acr:id-verified-dedup",
"age_over_21": true,
"nonce": "…",
"auth_time": 1792450000,
"iat": 1792450012,
"exp": 1792450612
}