Claims¶
Claims are JSON properties inside the id_token JWT and the userinfo response. The set you receive depends on the scopes you requested.
Standard claims (openid)¶
| Claim | Type | Description |
|---|---|---|
iss | string | Always https://id.littlexlittle.org. |
sub | string | Stable per-user identifier (the accounts.code value). |
aud | string | Your client_id. |
exp | int | Expiry (Unix timestamp). |
iat | int | Issued-at. |
auth_time | int | When the user last authenticated upstream. |
nonce | string | Echoed from the authorize request. Verify it matches what you sent. |
profile scope¶
| Claim | Type | Description |
|---|---|---|
name | string | Display name. |
given_name | string | First name. |
family_name | string | Last name. |
picture | string | URL to avatar (CDN-served). |
locale | string | BCP 47 locale, e.g. en-US. |
updated_at | int | Last profile change (Unix). |
email scope¶
| Claim | Type | Description |
|---|---|---|
email | string | Primary verified email if available, else primary unverified. |
email_verified | bool | Whether the email was verified by Little X Little. |
phone scope¶
| Claim | Type | Description |
|---|---|---|
phone_number | string | E.164 format. |
phone_number_verified | bool | Verified via SMS OTP. |
address scope¶
| Claim | Type | Description |
|---|---|---|
address.street_address | string | |
address.locality | string | City. |
address.region | string | State / province. |
address.postal_code | string | |
address.country | string | ISO 3166-1 alpha-2. |
address.formatted | string | Newline-joined full address. |
Little X Little custom claims¶
All custom claims are namespaced lxl.* to remain spec-compliant.
| Claim | Type | Scope | Description |
|---|---|---|---|
lxl.app | string | lxl.access | NGO app code, e.g. bootim. |
lxl.access | string[] | lxl.access | Permission strings, e.g. ["Website:Media","Donations:View"]. |
lxl.master | bool | lxl.master | True for master administrators. |
lxl.role | string | lxl.role | "Branch › Position" joined. |
lxl.links | string[] | lxl.links | Linked external providers, e.g. ["google","linkedin"]. |
Reading claims¶
php $payload = $client->verifyIdToken($id_token); if (in_array('Website:Media', $payload['lxl.access'] ?? [], true)) { // user can manage Website / Media on this NGO }
js function decode(jwt) { const [, payload] = jwt.split('.'); return JSON.parse(atob(payload.replace(/-/g,'+').replace(/_/g,'/'))); } const claims = decode(idToken); if (claims['lxl.master']) { /* admin features */ }
Decode ≠ verify
Decoding a JWT without verifying its signature is insecure. Never trust claims you haven't verified against JWKS — use a library that does both.