Xeonr Developer Docs
Guides

Authorization Code & Implicit

Implement user login with the authorization code flow, refresh tokens, and the implicit grant.

Authorization Code

The authorization code flow is a two-step redirect: the user is sent to the auth server, authenticates, then comes back to your app with a code that you exchange for tokens.

Endpoints

AuthorizationUser redirects to https://auth.xeonr.io/auth/authorize
Token exchangePOST https://auth.xeonr.io/api/v1/oauth/token
Token revocationPOST https://auth.xeonr.io/api/v1/oauth/revoke
UserInfoGET https://auth.xeonr.io/api/v1/userinfo
JWKSGET https://auth.xeonr.io/.well-known/jwks.json

Step 1 — Redirect the user to the authorization endpoint

Build a URL to https://auth.xeonr.io/auth/authorize and redirect the user's browser to it.

Required parameters:

ParameterValue
response_typecode
client_idYour client UUID
redirect_uriMust exactly match your registered redirect URI
scopeSpace-separated scopes (must include openid for ID tokens)
stateA random opaque string — verify this on return to prevent CSRF

Optional parameters:

ParameterDescription
code_challengeBase64url-encoded PKCE challenge (recommended for public clients)
code_challenge_methodS256 (recommended) or plain
nonceRequired if response_type includes id_token
max_ageMaximum authentication age in seconds
https://auth.xeonr.io/auth/authorize
  ?response_type=code
  &client_id=550e8400-e29b-41d4-a716-446655440000
  &redirect_uri=https%3A%2F%2Fmyapp.example.com%2Fcallback
  &scope=openid%20profile%20email
  &state=abc123
  &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
  &code_challenge_method=S256

Step 2 — Handle the redirect back

After the user authenticates, they are redirected to your redirect_uri with:

ParameterDescription
codeShort-lived authorization code — exchange this immediately
stateThe state value you sent — verify it matches
https://myapp.example.com/callback?code=AUTH_CODE&state=abc123

Reject the response if state doesn't match what you sent.

Step 3 — Exchange the code for tokens

POST /api/v1/oauth/token HTTP/1.1
Host: auth.xeonr.io
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=AUTH_CODE
&client_id=550e8400-e29b-41d4-a716-446655440000
&client_secret=YOUR_CLIENT_SECRET
&redirect_uri=https%3A%2F%2Fmyapp.example.com%2Fcallback
&code_verifier=YOUR_CODE_VERIFIER

Alternatively, pass client_id and client_secret as HTTP Basic auth:

Authorization: Basic base64(client_id:client_secret)

Parameters:

ParameterRequiredDescription
grant_typeYesauthorization_code
codeYesAuthorization code from the redirect
client_idYesYour client UUID
client_secretConfidential clientsYour client secret
redirect_uriYesMust match the original request exactly
code_verifierIf PKCE was used43–128 character base64url-encoded verifier

Response:

{
  "access_token": "eyJ...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "eyJ...",
  "id_token": "eyJ...",
  "scope": "openid profile email"
}

refresh_token is only present if you requested the offline_access scope. id_token is only present if you requested the openid scope.

Using the access token

Include the access token as a Bearer token on API requests:

Authorization: Bearer eyJ...

Fetching user data

Use the UserInfo endpoint to retrieve claims about the authenticated user. The token must include the openid scope.

GET /api/v1/userinfo HTTP/1.1
Host: auth.xeonr.io
Authorization: Bearer eyJ...

The response varies based on which scopes were granted:

{
  "sub": "urn:xeonr:user:12345",
  "email": "[email protected]",
  "email_verified": true,
  "nickname": "username",
  "preferred_username": "username",
  "picture": "https://cdn.upl.im/...",
  "groups": ["admin", "editor"]
}
FieldScope requiredDescription
subopenidAlways present. Stable user URN
emailemailUser's email address
email_verifiedemailAlways true for verified accounts
nicknameprofileUsername
preferred_usernameprofileUsername
pictureprofileAvatar URL, omitted if no avatar is set
groupsgroupsArray of role names within the application

To verify tokens independently, fetch the JWKS and validate the JWT signature:

GET https://auth.xeonr.io/.well-known/jwks.json

Refreshing tokens

If you requested offline_access, you received a refresh_token. Use it to get a new access token without user interaction.

POST /api/v1/oauth/token HTTP/1.1
Host: auth.xeonr.io
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token=eyJ...
&client_id=550e8400-e29b-41d4-a716-446655440000
&client_secret=YOUR_CLIENT_SECRET

Response:

{
  "access_token": "eyJ...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "eyJ...",
  "scope": "openid profile email"
}

The returned refresh_token replaces the previous one. Store it and discard the old value.

Requirements:

  • offline_access must have been in the original scope request
  • supports_refresh_token must be enabled on your client

Revoking tokens

To log a user out or invalidate a token:

POST /api/v1/oauth/revoke HTTP/1.1
Host: auth.xeonr.io
Authorization: Basic base64(client_id:client_secret)
Content-Type: application/x-www-form-urlencoded

token=eyJ...
&token_type_hint=refresh_token

token_type_hint is optional — either access_token or refresh_token.


Implicit grant

The implicit grant returns an access token directly in the URL fragment, skipping the code exchange. There are no refresh tokens.

This flow is only available on clients with supports_implicit_grant enabled. For new integrations, use Authorization Code with PKCE instead.

Redirect the user

https://auth.xeonr.io/auth/authorize
  ?response_type=token
  &client_id=550e8400-e29b-41d4-a716-446655440000
  &redirect_uri=https%3A%2F%2Fmyapp.example.com%2Fcallback
  &scope=openid%20profile
  &state=abc123

Handle the fragment response

The user is redirected to your redirect_uri with the token in the URL fragment (not the query string — it's not sent to your server):

https://myapp.example.com/callback
  #access_token=eyJ...
  &token_type=Bearer
  &expires_in=3600
  &state=abc123

Parse the fragment in the browser and verify state. The offline_access scope cannot be used with the implicit grant.

On this page