Skip to main content

Overview

The userinfo endpoint returns information about the user associated with the access token. This endpoint requires the email or openid scope.
Important: Auth Agent provides only the user’s email address to websites for account matching. No name or username is sent. Websites should use email as the primary identifier to match agents to user accounts.
GET https://api.auth-agent.com/userinfo

Authentication

Requires a valid access token with email or openid scope.
Authorization: Bearer {access_token}

Response

Success (200 OK)

{
  "sub": "agent_abc123",
  "email": "[email protected]"
}
sub
string
Agent ID (subject identifier)
email
string
User’s email address (only included if email or openid scope was granted). This is the primary identifier for matching agents to user accounts. Only email is provided - no name or username is sent.

Error (401 Unauthorized)

{
  "error": "invalid_request",
  "error_description": "Missing or invalid access token"
}

Example Requests

const userResponse = await fetch('https://api.auth-agent.com/userinfo', {
  headers: {
    'Authorization': `Bearer ${accessToken}`,
  },
});

const user = await userResponse.json();
// { sub: "agent_abc123", email: "[email protected]" }
// Only email is provided - no name or username

Integration Scenarios

The /userinfo endpoint is crucial for implementing different integration patterns:

Scenario 1: Full Account Access

Use the email to identify the user’s existing account and give the agent full access:
const user = await fetch('/userinfo', {
  headers: { Authorization: `Bearer ${accessToken}` }
}).then(r => r.json());

// Find existing user account by email
const existingUser = await db.users.findByEmail(user.email);

// Create session for agent with user's account
req.session.userId = existingUser.id;
req.session.isAgent = true;

Scenario 2: Contextual Profile

Create a separate agent profile but link it to the user’s account for context access:
const user = await fetch('/userinfo', {
  headers: { Authorization: `Bearer ${accessToken}` }
}).then(r => r.json());

// Find or create agent profile linked to user
const agentProfile = await db.agentProfiles.findOrCreate({
  agentId: user.sub,
  linkedUserId: (await db.users.findByEmail(user.email)).id,
});

req.session.agentProfileId = agentProfile.id;

Scenario 3: Fresh Profile

Do not call /userinfo - create a fresh agent profile with no user context:
// Extract agent ID from access token JWT
const decoded = jwt.decode(accessToken);

// Create fresh agent profile
const agentProfile = await db.agentProfiles.create({
  agentId: decoded.sub,
  // No user linkage
});

req.session.agentProfileId = agentProfile.id;

Learn More

Complete guide to integration scenarios with visual diagrams

Scope Requirements

The information returned depends on the scopes granted:
ScopeFields Returned
NoneOnly sub
email or openidsub, email (only email is provided - no name or username)
profileCurrently same as email

Security Considerations

The /userinfo endpoint exposes user email addresses. Only request the email scope if you need user context for your integration scenario.
Access tokens expire after 1 hour. Implement token refresh logic to maintain access.

Next Steps