Skip to main content
GET
/
api
/
oauth
/
userinfo
UserInfo Endpoint
curl --request GET \
  --url https://api.example.com/api/oauth/userinfo
{
  "sub": "<string>",
  "iss": "<string>",
  "name": "<string>",
  "preferred_username": "<string>",
  "picture": "<string>",
  "email": "<string>",
  "user_id": "<string>",
  "error": "<string>"
}
The UserInfo endpoint returns claims about the authenticated user based on the granted scopes. It supports both opaque access tokens and JWT access tokens.

Authentication

Requires a valid access token in the Authorization header:
Authorization: Bearer <access_token>
You can use either:
  • The opaque access_token from the token response
  • The access_token_jwt from the token response

Response

The response contains user claims based on the granted scopes.
sub
string
required
Subject identifier - the identity ID
iss
string
Issuer identifier (e.g., https://aveid.net)
name
string
Display name (requires profile scope)
preferred_username
string
User handle (requires profile scope)
picture
string
Avatar URL (requires profile scope)
email
string
Email address (requires email scope)
user_id
string
Ave user ID (requires user_id scope and app must be allowed to access it)

Scope Requirements

ClaimRequired ScopeNotes
sub(always included)Identity ID
iss(always included)Issuer URL
nameprofileDisplay name
preferred_usernameprofileUser handle
pictureprofileAvatar URL
emailemailEmail address
user_iduser_idOnly if app has allowUserIdScope

Example Request

import { fetchUserInfo } from '@ave-id/sdk';

const userInfo = await fetchUserInfo(
  {
    clientId: 'your_client_id',
    redirectUri: 'https://yourapp.com/callback',
  },
  accessToken
);

console.log(userInfo.sub); // Identity ID
console.log(userInfo.name); // Display name
console.log(userInfo.email); // Email

Example Response

With profile and email scopes

{
  "sub": "550e8400-e29b-41d4-a716-446655440000",
  "iss": "https://aveid.net",
  "name": "Alice Smith",
  "preferred_username": "alice",
  "picture": "https://cdn.aveid.net/avatars/alice.jpg",
  "email": "[email protected]"
}

With user_id scope (if allowed)

{
  "sub": "550e8400-e29b-41d4-a716-446655440000",
  "iss": "https://aveid.net",
  "name": "Alice Smith",
  "preferred_username": "alice",
  "picture": "https://cdn.aveid.net/avatars/alice.jpg",
  "email": "[email protected]",
  "user_id": "usr_7b9c2f1e3a6d8h4j"
}

Minimal response (no optional scopes)

{
  "sub": "550e8400-e29b-41d4-a716-446655440000",
  "iss": "https://aveid.net"
}

Error Responses

error
string
Error code:
  • unauthorized - Missing or invalid Authorization header
  • invalid_token - Access token is invalid or expired

Example Errors

Missing Token
{
  "error": "unauthorized"
}
Expired Token
{
  "error": "invalid_token"
}

Token Types

The endpoint accepts both token types returned from the token endpoint:
  1. Opaque Access Token (access_token)
    • Stored in-memory on the server
    • Validated against internal store
  2. JWT Access Token (access_token_jwt)
    • Self-contained signed JWT
    • Verified using public JWK from /.well-known/jwks.json
    • Contains claims: sub, sid, cid, scope, aud, iss, exp, iat
Use the JWT access token for stateless verification across distributed systems. Use the opaque token for server-side sessions.

Integration Example

Complete flow from authorization to fetching user info:
import { exchangeCode, fetchUserInfo } from '@ave-id/sdk';

// 1. Exchange authorization code for tokens
const tokens = await exchangeCode(
  {
    clientId: 'your_client_id',
    redirectUri: 'https://yourapp.com/callback',
  },
  {
    code: authorizationCode,
    codeVerifier: codeVerifier,
  }
);

// 2. Fetch user info
const userInfo = await fetchUserInfo(
  {
    clientId: 'your_client_id',
    redirectUri: 'https://yourapp.com/callback',
  },
  tokens.access_token
);

// 3. Use user info
console.log(`Welcome, ${userInfo.name}!`);

Build docs developers (and LLMs) love