UserInfo Endpoint — Retrieving User Identity Data in OpenID Connect
In this tutorial, you will learn about UserInfo Endpoint. We cover key concepts, practical examples, and best practices to help you master this topic.
The UserInfo endpoint is an OAuth2-protected resource that returns claims about the authenticated user, often including profile data not present in the ID token, accessible by presenting a valid access token.
What You'll Learn
- How the UserInfo endpoint works and when to use it
- Making authenticated requests to UserInfo
- Comparing UserInfo data with ID token claims
Why It Matters
ID tokens can become large if they include all user claims. Providers may limit ID token size and include only essential claims. The UserInfo endpoint provides a complete picture of the user without bloating the token, and can be called when additional data is needed.
Real-World Use
Doda Browser's ID token includes only sub, email, and name to keep the token small. When the user visits their profile page, the browser calls the UserInfo endpoint with the access token to fetch the full profile including address, phone, and picture.
flowchart LR
App["Your App"] -->|"Access Token"| UI["UserInfo Endpoint"]
UI -->|"Claims JSON"| App
App -->|"ID Token (compact)"| Provider["OIDC Provider"]
Provider --> App
style UI fill:#dbeafe,stroke:#2563eb
Calling the UserInfo Endpoint
import requests
def get_user_info(access_token, userinfo_endpoint):
resp = requests.get(
userinfo_endpoint,
headers={"Authorization": f"Bearer {access_token}"}
)
if resp.status_code == 200:
return resp.json()
else:
print(f"Error: {resp.status_code} - {resp.text}")
return None
# Example
userinfo = get_user_info(
access_token="ya29.a0AfH6S...",
userinfo_endpoint="https://www.googleapis.com/oauth2/v3/userinfo"
)
print(json.dumps(userinfo, indent=2))
Expected output:
{
"sub": "1234567890",
"name": "Alice Smith",
"given_name": "Alice",
"family_name": "Smith",
"picture": "https://example.com/photo.jpg",
"email": "alice@example.com",
"email_verified": true,
"locale": "en",
"hd": "dodatech.com"
}
ID Token vs. UserInfo Claims
| Aspect | ID Token | UserInfo Response |
|---|---|---|
| Access method | Embedded in JWT | API call with access token |
| Freshness | Issued at auth time | Always current |
| Size | Limited (compact) | Can include full profile |
| Signature | Digitally signed | Response is not signed |
| Availability | Always returned | Requires network call |
When to Use UserInfo vs. ID Token
Use the ID token for initial authentication and basic user identification. It contains the essential claims and is signed, so you can trust it immediately.
Use the UserInfo endpoint when you need additional claims not in the ID token, when data may have changed since authentication (profile picture, address), or when you need the most current data.
def get_user_profile(id_token_claims, access_token, userinfo_endpoint):
profile = {
"id": id_token_claims["sub"],
"email": id_token_claims.get("email"),
}
# Fetch additional data from UserInfo
userinfo = get_user_info(access_token, userinfo_endpoint)
if userinfo:
profile["name"] = userinfo.get("name")
profile["picture"] = userinfo.get("picture")
profile["locale"] = userinfo.get("locale")
else:
# Fallback to ID token claims
profile["name"] = id_token_claims.get("name")
profile["picture"] = id_token_claims.get("picture")
return profile
UserInfo Response Validation
The UserInfo response is not signed. If you need verified claims, rely on the ID token. For UserInfo, ensure the sub claim matches the ID token's sub:
def validate_userinfo(userinfo, id_token_sub):
if userinfo.get("sub") != id_token_sub:
raise ValueError("UserInfo sub does not match ID token sub")
return True
Common Mistakes
1. Calling UserInfo for Every Page Load
ID token claims are sufficient for most UI rendering. Call UserInfo only when you need claims not in the ID token, not on every request.
2. Not Handling UserInfo Errors Gracefully
The UserInfo endpoint may fail. Your app should still function using only ID token claims as a fallback.
3. Trusting Unsigned UserInfo Data
The UserInfo response is not signed. Verify the sub matches the ID token to ensure the data belongs to the correct user.
4. Using a Stale Access Token
Access tokens expire. If the UserInfo call fails with 401, refresh the access token before retrying.
5. Expecting All Claims in Every Response
The UserInfo endpoint only returns claims for the scopes you requested. If you did not request profile scope, do not expect name.
Practice Questions
- When should you use the UserInfo endpoint instead of the ID token?
- How does the UserInfo endpoint authenticate requests?
- Why is the UserInfo response not signed?
- What should you verify when comparing UserInfo and ID token data?
- How can you handle a failed UserInfo request gracefully?
Answers:
- Use UserInfo when you need claims not included in the ID token or when you need the most current data.
- The request includes the access token in the
Authorization: Bearer <token>header. - The response is protected by HTTPS, and the connection is authenticated by the access token. Signing is not required.
- Verify the
subclaim in the UserInfo response matches thesubclaim in the ID token to prevent data mismatch. - Fall back to claims from the ID token and continue without the additional UserInfo data.
Challenge: Build a user profile service that combines ID token claims with UserInfo data. Cache UserInfo responses for 5 minutes to reduce API calls while keeping data reasonably fresh.
FAQ
Mini Project
Create a Python app that authenticates with an OIDC provider, extracts claims from the ID token, then calls the UserInfo endpoint for additional data. Implement Caching so UserInfo is called at most once every 5 minutes per user. Handle token expiration gracefully.
What's Next
Continue with Discovery URL and Well-Known Config to understand how OIDC clients discover provider endpoints, or explore OIDC Scopes for controlling claim access.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro