Read OpenID Connect claims correctly
OpenID Connect layers identity on top of OAuth 2.0 by returning claims about the
authenticated user. Some claims are protocol metadata in the ID token (iss,
sub, aud, exp, nonce); others describe the person and are released by
scope (profile, email, phone, address). This tool lists the standard
claims with their JSON data type, the scope that unlocks them, and where they
appear — the ID token, the UserInfo endpoint, or both.
How it works
When a client requests scopes during login, the authorization server releases the
matching claims after the user consents. The mandatory openid scope yields
sub, the stable user identifier. The profile scope releases display claims such
as name, given_name, picture, locale and updated_at; email releases
email and email_verified; phone releases phone_number and its verified
flag; and address releases a structured address JSON object. Protocol claims in
the ID token let the client validate the token: iss and aud must match the
expected issuer and client, exp bounds its lifetime, and nonce ties it back to
the original request to prevent replay. The same profile claims can be fetched
fresh from the /userinfo endpoint using the access token.
Claims by scope — quick reference
| Scope | Claims released |
|---|---|
openid (mandatory) | sub, iss, aud, exp, iat, nonce |
profile | name, given_name, family_name, middle_name, nickname, preferred_username, profile, picture, website, gender, birthdate, zoneinfo, locale, updated_at |
email | email, email_verified |
phone | phone_number, phone_number_verified |
address | address (structured object: formatted, street_address, locality, region, postal_code, country) |
Common implementation mistakes
Using email as the user key. Email addresses change and can be reused across
accounts. Always store sub (with iss as namespace if multi-provider) as your
primary user identifier. You can display email and even let users search by it,
but key your database on sub.
Trusting email without checking email_verified. A false or absent
email_verified claim means the provider has not confirmed the user controls
that address. Never grant password-reset rights, send sensitive notifications, or
link accounts based solely on a matching email that is not verified.
Not validating the ID token. Before reading any claim, verify the JWT
signature against the provider’s JWKS, check iss matches the expected issuer,
check aud contains your client ID, and check exp is in the future. A missing
nonce check opens replay attacks when using the implicit or hybrid flow.
Reading address as a string. The address claim is a JSON object, not a
flat string. Access address.formatted, address.postal_code, and
address.country as sub-fields.
Tips and notes
Key your accounts on sub, never on email or preferred_username, both of which
can change or be reused. Check email_verified before trusting an address, and
remember address is a nested JSON object — read its formatted, country and
postal_code sub-fields rather than expecting a plain string. Request only the
scopes you genuinely need so the consent screen stays minimal and you collect less
personal data. Finally, always validate the ID token’s signature, iss, aud,
exp and nonce before trusting any claim inside it.