ID token & UserInfo
העתקת עמוד
The id_token claims — including amr (how the user authenticated) and auth_time — and the UserInfo endpoint (GET|POST /api/oauth/userinfo) that returns scope-gated identity claims.
עודכן
OpenID Connect gives you two sources of identity: the id_token returned by the token endpoint (a signed statement about who signed in and how), and the UserInfo endpoint (a live, server-verified lookup of the user’s claims). Both are gated by the scopes the user granted.
The id_token
Issued when the openid scope is granted. It is an RS256 JWT (typ: JWT) that verifies offline against the JWKS.
Claims
| Claim | Always | Meaning |
|---|---|---|
iss | ✓ | Issuer — https://entrybit.net. |
sub | ✓ | Stable EntryBit user identifier. |
aud | ✓ | Your client_id. |
iat | ✓ | Issued-at (Unix seconds). |
exp | ✓ | Expiry (Unix seconds). |
nonce | Echoed from your authorize request — verify it matches. | |
auth_time | When the user actually authenticated (Unix seconds). | |
amr | How the user authenticated (see below). | |
at_hash | Binds the id_token to the access token. | |
email, email_verified | With the email scope. | |
name, picture | With the profile scope. |
amr — how the user signed in
The amr (Authentication Methods References, RFC 8176) array records the factors used at login. EntryBit stamps these values:
| Value | Meaning |
|---|---|
pwd | Password. |
otp | One-time code (authenticator / email). |
sms | SMS one-time code. |
swk | Passkey (software-backed key). |
user | Passkey with user verification. |
fed | Federated login (Google). |
mfa | Two or more factors were used. |
For example, ["swk","user"] is a verified passkey, ["pwd","otp","mfa"] is password plus a code, and ["fed"] is Google. Combined with auth_time, this lets a sensitive screen require a recent or stronger login — request one with prompt=login or max_age on the authorize request.
Validating it yourself
If you decode the id_token on the client, fully validate the JWT — do not trust decoded claims blindly:
- Verify the signature against
/.well-known/jwks.json. - Check
iss==https://entrybit.net. - Check
aud== yourclient_id. - Check
expis in the future. - Check
nonceequals the value you sent (so makenoncerequired if you consume the id_token). Many libraries — includingexpo-auth-session— do not validate id_tokens for you.
With jose in Node.js, steps 1–4 are options and step 5 is yours:
// npm install jose
import { createRemoteJWKSet, jwtVerify } from 'jose';
const JWKS = createRemoteJWKSet(new URL('https://entrybit.net/.well-known/jwks.json'));
export async function verifyIdToken(idToken: string, expectedNonce: string) {
// Steps 1–4 — signature, iss, aud, exp — enforced by jose.
const { payload } = await jwtVerify(idToken, JWKS, {
issuer: 'https://entrybit.net',
audience: CLIENT_ID,
algorithms: ['RS256'],
});
// Step 5 — the nonce binds this id_token to YOUR authorize request.
if (payload.nonce !== expectedNonce) {
throw new Error('id_token nonce mismatch — possible replay');
}
return payload; // { sub, amr?, auth_time?, email?, name?, … }
}If you only need the user’s profile, prefer UserInfo below — it is already server-verified.
UserInfo endpoint
Returns the signed-in user’s claims, gated by the granted scopes. Available over GET and POST (OIDC Core §5.3.1 — the two are identical).
GET /api/oauth/userinfo
POST /api/oauth/userinfo
Authorization: Bearer <access_token>Requires the openid scope. The email and profile scopes gate their respective claims.
curl https://entrybit.net/api/oauth/userinfo \
-H "Authorization: Bearer $ACCESS_TOKEN"Response
{
"sub": "usr_9f1c2ab34cd56ef7",
"email": "dana@example.com",
"email_verified": true,
"name": "Dana Cohen",
"picture": "https://media.entrybit.net/media/avatars/…/full/….webp"
}| Field | Present when |
|---|---|
sub | Always (with openid). |
email, email_verified | The email scope was granted. |
name, picture | The profile scope was granted. |
picture, here and in the id_token, is always an absolute https:// URL: the 256px copy of an uploaded photo on media.entrybit.net, or the address of the user’s Google picture. It is omitted when the account has no picture, so treat it as optional even with the profile scope.
Errors
401/403 responses carry a WWW-Authenticate: Bearer challenge:
| Status | error | Meaning |
|---|---|---|
401 | invalid_token | Missing, expired, or invalid access token — refresh or re-login. |
403 | insufficient_scope | The token lacks openid. |
See Errors for the full Bearer-challenge contract.

