Scopes & Claims
Scopes control what user data your application can access. Claims are the individual pieces of data returned when you call the UserInfo endpoint or decode the ID token. Request only the scopes you need — users see what you are requesting on the consent screen.
Available scopes
| Scope | Description | Claims included |
|---|---|---|
openid | Required. Identifies the user | sub |
profile | Basic profile information | preferred_username, display_name, picture, created_at |
email | User's email address | email, email_verified |
age_verification | Verified age bracket | age_verified, age_bracket, age_brackets_verified, verification_level, verified_at |
connections | Connection details for your site | connection (object with connected_at, last_used_at, scopes_granted) |
Scope details and examples
openid (required)
This scope is always required. It returns the user's unique Xident ID as the sub claim.
This identifier is stable and will not change — use it as the primary key for your user records.
// scope: openid
// Returns the user's unique identifier
{
"sub": "xid_abc123def456"
} profile
Returns basic profile information. None of this is PII — usernames and display names are chosen by the user and can be changed. The picture is a Xident-hosted avatar.
// scope: openid profile
// Returns basic profile info (no PII)
{
"sub": "xid_abc123def456",
"preferred_username": "alex_t",
"display_name": "Alex T.",
"picture": "https://api.xident.io/avatars/xid_abc123def456.jpg",
"created_at": "2026-01-10T08:00:00Z"
} email
Returns the user's email if they have one registered and consent to sharing it.
The email_verified claim tells you whether the email has been confirmed.
// scope: openid email
// Returns the user's email (if they have one and consented)
{
"sub": "xid_abc123def456",
"email": "alex@example.com",
"email_verified": true
} age_verification
This is Xident's unique differentiator. No other OAuth provider offers cryptographically verified age information. The age bracket was established through ML-based liveness detection, document verification, or both — it is not self-reported.
// scope: openid age_verification
// Returns verified age information — Xident's unique differentiator
{
"sub": "xid_abc123def456",
"age_verified": true,
"age_bracket": "18+",
"age_brackets_verified": ["12+", "15+", "18+"],
"verification_level": "ml",
"verified_at": "2026-02-15T10:30:00Z"
} | Claim | Type | Description |
|---|---|---|
age_verified | boolean | Whether the user has completed age verification |
age_bracket | string | The highest verified bracket: "12+", "15+", "18+", "21+", or "25+" |
age_brackets_verified | string[] | All brackets the user is verified for (e.g., a 20-year-old verified as 18+ is also 15+ and 12+) |
verification_level | string | How they were verified: "ml" (liveness + ML), "document" (OCR + face match), or "both" |
verified_at | string | ISO 8601 timestamp of when the verification was completed |
Privacy by design
The age_verification scope gives you a bracket (e.g., "18+"), not an exact age or birthdate.
No face images, document scans, or personal information are shared. You get a verified pass/fail — nothing more.
connections
Returns metadata about the user's connection to your site. You can only see your own connection — not the user's connections to other sites.
// scope: openid connections
// Returns the user's connected sites (only your site's connection)
{
"sub": "xid_abc123def456",
"connection": {
"connected_at": "2026-02-15T10:30:00Z",
"last_used_at": "2026-03-10T14:22:00Z",
"scopes_granted": ["openid", "age_verification", "profile"]
}
} Combining scopes
You can request multiple scopes in a single authorization request. Here is an example with all scopes:
// scope: openid profile email age_verification connections
// All scopes combined
{
"sub": "xid_abc123def456",
"preferred_username": "alex_t",
"display_name": "Alex T.",
"picture": "https://api.xident.io/avatars/xid_abc123def456.jpg",
"created_at": "2026-01-10T08:00:00Z",
"email": "alex@example.com",
"email_verified": true,
"age_verified": true,
"age_bracket": "18+",
"age_brackets_verified": ["12+", "15+", "18+"],
"verification_level": "ml",
"verified_at": "2026-02-15T10:30:00Z",
"connection": {
"connected_at": "2026-02-15T10:30:00Z",
"last_used_at": "2026-03-10T14:22:00Z",
"scopes_granted": ["openid", "profile", "email", "age_verification", "connections"]
}
} Common use case: age-gated content
For most age verification use cases, you only need openid and age_verification.
This is the minimal scope set for age-gated content:
// Most common use case: age-gated content
// scope: openid age_verification
const params = new URLSearchParams({
client_id: 'xc_abc123',
redirect_uri: 'https://yoursite.com/callback',
response_type: 'code',
scope: 'openid age_verification', // Just these two
code_challenge: codeChallenge,
code_challenge_method: 'S256',
state: state,
}); Fetching claims
After obtaining an access token, you can fetch claims from the UserInfo endpoint or decode them from the ID token (if the scope was included in the authorization request).
// Fetch claims from the UserInfo endpoint
const response = await fetch('https://api.xident.io/oauth/userinfo', {
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
const claims = await response.json();
// Check age verification
if (claims.age_verified && claims.age_brackets_verified.includes('18+')) {
// User is verified 18+
grantAccess();
} else {
// User is not verified for this age bracket
showAgeRestrictionMessage();
} Privacy guarantees
- No face images — Face data never leaves the user's device during ML verification
- No documents — Document images are deleted immediately after OCR processing
- No birthdate — Only the verified age bracket is stored and shared
- No cross-site tracking — Your site cannot see connections to other sites
- User-controlled — Users can revoke your site's access at any time from their Xident account
- GDPR-compliant — Hard-delete on account deletion, no data retention
Next steps
- Token Management — Access tokens, refresh tokens, and JWT verification
- Security Best Practices — Harden your OAuth integration
- API Reference — Full endpoint documentation