> ## Documentation Index
> Fetch the complete documentation index at: https://docs.world.org/llms.txt
> Use this file to discover all available pages before exploring further.

# ID tokens and identity

> Validate token claims, read UserInfo, and recognize accounts using the issuer and pairwise subject.

World ID credentials, token responses, claim semantics, authentication methods, and account identifiers.

## Credentials and authentication classes

Choose which verification your application accepts separately from how recently
the person must authenticate. A World ID account can hold both Orb and Selfie
Check credentials, plus passkeys for authentication.

| Credential | What it establishes | Baseline `acr` |
| - | - | - |
| Orb | Iris-based verification at an Orb provides high assurance of unique humanness. | `https://world.org/oidc/acr/orb` |
| Selfie Check | Camera-based liveness and facial similarity checks provide a medium-assurance signal of humanness and uniqueness, with greater duplicate-account risk than Orb. | `https://world.org/oidc/acr/selfie` |
| Passkey | Authenticates control of the account with WebAuthn user verification. It adds no biometric uniqueness verification. | The account's Orb or Selfie Check class, or no `acr` if it holds neither. |

[Orb verification](https://docs.world.org/world-id/credentials/1.md) is suited to
applications that need stronger resistance to duplicate accounts.
[Selfie Check](https://docs.world.org/world-id/credentials/11.md) is available without
an Orb visit. It does not provide a strict one-person-one-account guarantee.
Choose according to the consequences of accepting a duplicate account.

**Face Auth adds a face check during authentication with an existing credential.**
`https://world.org/oidc/acr/orb-face` adds a completed face check to an Orb proof;
`https://world.org/oidc/acr/selfie-face` adds it to a Selfie Check proof. A Selfie
Check credential by itself does not mean a face check occurred during this login.
A passkey cannot satisfy either `-face` class.

Use `acr` for the achieved class, `amr` for the authentication method, and
`auth_time` for freshness. An account's verification type does not imply a fresh
biometric check. See [Assurance values](#assurance-values)
for the exact claims and [Accept Orb or Selfie Check](https://docs.world.org/agent-pass/step-up.md#accept-orb-or-selfie-check)
for requests that allow either credential.

## Token response

Browser and device flows both return `id_token`, `access_token`, `token_type`, and
`expires_in`:

* **`id_token`:** the signed authentication result described below.
  [Validate it](https://docs.world.org/agent-pass/connect-your-backend.md#validate-the-id-token) before using
  any claim.
* **`access_token`:** an opaque credential whose authority is limited to the
  [UserInfo endpoint](#userinfo).
* **`token_type`:** `Bearer`.
* **`expires_in`:** the access token's lifetime in seconds. Read the returned
  value. The ID token has its own expiration, given by `exp`.

Refresh tokens are available only through the
[XAA profile](https://docs.world.org/agent-pass/xaa.md), which returns a rotating refresh token
for `openid offline_access`.

After validation, your backend creates its own application sessions and API or
MCP credentials. Keep the ID token and subject in your backend, outside model
messages and tool results.

## Decoded ID token

World IdP signs ID tokens with RS256; `kid` selects a key from
[discovery's `jwks_uri`](https://auth.world.org/.well-known/openid-configuration). Use an OIDC library for [ID token validation](https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation).
This illustrative browser response includes the requested nonce:

```json theme={"system"}
{
  "iss": "https://auth.world.org",
  "sub": "<opaque-subject>",
  "aud": "<registered-client-id>",
  "exp": 1790000420,
  "iat": 1790000120,
  "jti": "<token-identifier>",
  "auth_time": 1790000000,
  "acr": "https://world.org/oidc/acr/orb",
  "amr": ["pop"],
  "nonce": "<nonce-from-your-request>"
}
```

## Claim reference

| Claim | World IdP behavior |
| - | - |
| `iss`, `sub` | Store the exact issuer and opaque, case-sensitive subject together as the external account identity. |
| `aud` | Your registered client ID. Clients sharing a sector still have separate token audiences. |
| `auth_time` | Server verification time for the proof or passkey assertion. See [Assurance values](#assurance-values). |
| `acr`, `amr` | Achieved class and methods; see [Assurance values](#assurance-values). Selfie classes require a request or [accepted accounts](https://docs.world.org/agent-pass/step-up.md#accepted-accounts) that list them. Any account also permits Selfie or unverified accounts; unverified accounts omit `acr`. |
| `nonce` | Included when supplied in browser authorization; omitted in device grants. |

Apply standard `exp`, `iat`, and `jti` semantics. Read `exp` from the ID token;
`expires_in` describes the access token. Use `sub` for account recognition.

For example, if a user authenticates at 10:00 and their existing session produces
a token at 11:00, `auth_time` still represents 10:00 while `iat` represents 11:00.
Use `auth_time` for authentication freshness, as described in
[Step-up authentication](https://docs.world.org/agent-pass/step-up.md).

For accounts with an enabled inbox, newly issued ID tokens and ID-JAGs also
include `email` and `email_verified: true`. Clients may request the `email` scope;
enabled aliases are included whether or not it is requested. The immutable address is
`<sub>@<receiving-domain>`, using the subject for the receiving application's
sector. Clients sharing a sector share an address; different sectors receive
different addresses. An ID-JAG uses the target app's subject and address. The
email claim may support partner account provisioning, but does not authorize
reading the inbox or connecting an app.
Deleting an account permanently retires its aliases. If an account's subject
matches a retired alias, authentication still works but its email claim is omitted.
Keep `(iss, sub)` as the account identity and require explicit account linking.

Name, raw World identifiers, and World proofs are not included. See the
[OIDC claim definitions](https://openid.net/specs/openid-connect-core-1_0.html#IDToken)
and [identity stability rules](https://openid.net/specs/openid-connect-core-1_0.html#ClaimStability).

## Assurance values

* **`acr`:** `https://world.org/oidc/acr/orb` means the account holds a verified
  Orb credential, and the person authenticated with a proof of that credential or
  an enrolled passkey. `https://world.org/oidc/acr/orb-face` additionally requires
  the World ID app to report a completed Face Auth check for the proof request.
  `https://world.org/oidc/acr/selfie` and `https://world.org/oidc/acr/selfie-face` mean
  the same for a Selfie Check credential.
* **`amr`:** `["pop"]` for a World ID proof with either credential; `acr` names the credential.
  A face check during the login adds `face` and `user`, giving `["pop", "face", "user"]`.
  `["pop", "user", "mfa"]` identifies a user-verified passkey, which does not assert
  a fresh World proof. Only the passkey value asserts MFA.
* **`auth_time`:** server verification time for the credential proof or passkey assertion, not
  the phone's exact proof-generation or biometric-check time. Browser-session reuse
  preserves it and the original `acr` and `amr`; a new token's `iat` does not imply
  a fresh proof.

Face Auth assurance trusts the official app's completion signal together with
the verified proof. The server does not independently verify the selfie check.
A missing or false completion signal cannot satisfy a face check class,
including when the signal is missing from an older app.

## Authentication methods

For fresh authentication, World IdP verifies a credential proof or an enrolled
passkey assertion with WebAuthn user presence and user verification. A passkey
assertion completes authentication without a phone proof. Possession of a
verification link alone cannot complete authentication.

Only the initiating browser can claim a browser transaction's session and
callback URL. Device grants create no browser session; redemption requires the
private device code and the registered client's authentication.

The ID token carries authentication context. Your application checks permissions
and enforces and records any approval required for a payment, redemption, or
account change.

## UserInfo

Send `GET` or `POST` to the discovery document's `userinfo_endpoint` with
`Authorization: Bearer <access_token>`. UserInfo returns `sub` and, when the
account's inbox is enabled, `email` and `email_verified`. Require its `sub` to
match the validated ID token before using the claims. Cookies, ID tokens, and
query-string credentials do not authenticate this endpoint.

Access tokens expire within five minutes. UserInfo reads from a database follower,
so revocation and account, client, consent, or XAA grant changes take effect after
replication. A stale follower can accept a revoked token until replication catches
up or the token expires. Reauthorizing a revoked connection does not revive its
old tokens after replication. The authenticated issuing client can revoke a token
at the discovery document's `revocation_endpoint`.
Revoking an XAA access token revokes its delegation family.

## Browser sessions

World IdP sessions expire after 180 days without authenticated browser activity.
Activity renews that deadline; logout, revocation, account disablement, and
requested reauthentication still apply. Session reuse preserves the original
authentication context.

## Store and match sub

After validating the ID token, store **`(iss, sub)`** as the external identity
linked to your application's account. Link World ID through an explicit action while
the user is signed in to that account. For later step-up, require the returned
issuer and subject to match the stored pair before updating the session's assurance.

Treat `sub` as an opaque, case-sensitive string. Store and compare the complete
value exactly as issued. For this OIDC account binding, use the subject from the
validated ID token.

For the same issuer and registered sector, the same World ID account receives
the same `sub` across browser sign-ins, devices, and agent authentication flows.

A **sector** is the registered scope in which applications share subject identifiers.
The subject is **pairwise**: different sectors receive different values for the
same account. Clients deliberately registered in the same sector receive the
same value. Rotating a client secret or using a new client ID within that sector
does not change the subject. Choose your sector before integrating; see
[Manage credentials and callbacks](https://docs.world.org/agent-pass/app-registration.md#manage-credentials-and-callbacks).

A new World identity can produce a new subject. Do not automatically merge
accounts with different subjects or infer a mapping between sectors.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.