Authorization Code Flow OpenID Connect
OpenID Connect Authorization Code Flow
OpenID Connect (OIDC) Authorization Code Flow is the most secure and widely recommended flow for authenticating users in web and mobile applications. It separates the user-facing browser interaction from the back-channel token exchange, ensuring that tokens are never exposed in the browser.
This page covers the end-to-end flow as implemented by LoginRadius, including the Authorization Endpoint, the Callback, and the Token Exchange.
Overview
The flow operates in two distinct phases:
- Authorization Phase — runs in the browser. The client redirects the user to the LoginRadius OIDC Authorization endpoint. After the user authenticates, LoginRadius redirects back to the client with the
authorization_code. - Token Exchange Phase — runs server-side (back-channel). The client exchanges the
authorization_codefor anaccess_token,id_token, and optionally arefresh_tokenby making a direct call to the Token endpoint.
Flow Diagram
Step-by-Step Walkthrough
Step 1 — Authorization Request
The client application redirects the user's browser to the LoginRadius OIDC Authorization endpoint.
Endpoint
GET https://{SiteURL}/service/oidc/{OIDCAppName}/authorize
SiteURL= Either<TenantName>.hub.loginradius.comor CustomDomain i.e.auth.your-app.com.OIDCAppName= your configured OIDC App name
Example Request
GET https://your-app.hub.loginradius.com/service/oidc/MyApp/authorize
?client_id=YOUR_OIDC_CLIENT_ID
&response_type=code
&scope=openid%20profile%20email
&redirect_uri=https://your-app.com/callback
&state=abc123xyz
Step 2 — Session Check
Upon receiving the request, LoginRadius checks whether the user already has an active authenticated session.
- If an active session is found → LoginRadius skips the login UI and immediately redirects to
redirect_uriwith the authorization code. - If no active session → LoginRadius renders the login UI for the user to authenticate.
Step 3 — User Authentication
The user authenticates via the login page. Two login paths are supported:
- Traditional Login — The user submits their credentials (email/password or phone).
- Social Login — The user authenticates via a configured social provider.
After successful authentication, LoginRadius generates a one-time, short-lived authorization_code and redirects back to the client's redirect_uri.
Step 4 — Authorization Code Issuance
After the user authenticates, LoginRadius redirects to the client callback with the authorization code appended as a query parameter.
Success Response
HTTP 302
Location: https://your-app.com/callback?code={authorization_code}&state=abc123xyz
Error Response
HTTP 302
Location: https://your-app.com/callback?error=access_denied&error_description=...
Errors are returned as query parameters on the redirect_uri by default. This behavior can be changed by passing the response_mode parameter in the authorization request.
Step 5 — Token Exchange
The client backend makes a direct POST call to the LoginRadius Token endpoint to exchange the authorization code for tokens. This call never goes through the browser.
Endpoint
POST https://{SiteURL}/api/oidc/{OIDCAppName}/token
The token endpoint accepts two content types:
| Content-Type | Description |
|---|---|
application/x-www-form-urlencoded | Parameters sent as a URL-encoded form body |
application/json | Parameters sent as a JSON object in the request body |
Client Auth - Client Secret Basic
The client_id and client_secret are passed as a Base64-encoded Authorization header (Basic Base64(client_id:client_secret)). They must not be included in the request body.
application/x-www-form-urlencoded
application/json
POST /api/oidc/{OIDCAppName}/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic Base64(YOUR_OIDC_CLIENT_ID:YOUR_OIDC_CLIENT_SECRET)
grant_type=authorization_code
&code={authorization_code}
&redirect_uri=https://your-app.com/callback
POST /api/oidc/{OIDCAppName}/token
Content-Type: application/json
Authorization: Basic Base64(YOUR_OIDC_CLIENT_ID:YOUR_OIDC_CLIENT_SECRET)
{
"grant_type": "authorization_code",
"code": "{authorization_code}",
"redirect_uri": "https://your-app.com/callback"
}
Client Auth - Client Secret Post
The client_id and client_secret are included directly in the request body.
application/x-www-form-urlencoded
application/json
POST /api/oidc/{OIDCAppName}/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code={authorization_code}
&client_id=YOUR_OIDC_CLIENT_ID
&client_secret=YOUR_OIDC_CLIENT_SECRET
&redirect_uri=https://your-app.com/callback
POST /api/oidc/{OIDCAppName}/token
Content-Type: application/json
{
"grant_type": "authorization_code",
"code": "{authorization_code}",
"client_id": "YOUR_OIDC_CLIENT_ID",
"client_secret": "YOUR_OIDC_CLIENT_SECRET",
"redirect_uri": "https://your-app.com/callback"
}
Client Secret Post
Client Secret Basic
The client_id and client_secret are included directly in the request body.
Using application/x-www-form-urlencoded
POST /api/oidc/{OIDCAppName}/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code={authorization_code}
&client_id=YOUR_OIDC_CLIENT_ID
&client_secret=YOUR_OIDC_CLIENT_SECRET
&redirect_uri=https://your-app.com/callback
Using application/json
POST /api/oidc/{OIDCAppName}/token
Content-Type: application/json
{
"grant_type": "authorization_code",
"code": "{authorization_code}",
"client_id": "YOUR_OIDC_CLIENT_ID",
"client_secret": "YOUR_OIDC_CLIENT_SECRET",
"redirect_uri": "https://your-app.com/callback"
}
The client_id and client_secret are passed as a Base64-encoded Authorization header (Basic Base64(client_id:client_secret)). They must not be included in the request body.
Using application/x-www-form-urlencoded
POST /api/oidc/{OIDCAppName}/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic Base64(YOUR_OIDC_CLIENT_ID:YOUR_OIDC_CLIENT_SECRET)
grant_type=authorization_code
&code={authorization_code}
&redirect_uri=https://your-app.com/callback
Using application/json
POST /api/oidc/{OIDCAppName}/token
Content-Type: application/json
Authorization: Basic Base64(YOUR_OIDC_CLIENT_ID:YOUR_OIDC_CLIENT_SECRET)
{
"grant_type": "authorization_code",
"code": "{authorization_code}",
"redirect_uri": "https://your-app.com/callback"
}
Success Response
{
"access_token": "<LoginRadius JWT Access Token>",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "<Refresh Token>",
"id_token": "<JWT ID Token>"
}
Authorization Request Parameters
| # | Parameter | Required | Description |
|---|---|---|---|
| 1 | client_id | ✅ Required | Your OIDC application client_id |
| 2 | redirect_uri | ✅ Required | Callback URL of your application. Must be whitelisted in the Admin Console. |
| 3 | response_type | ✅ Required | Must be code for the Authorization Code Flow |
| 4 | scope | ✅ Required | Space-delimited list of scopes. Must include openid. Other supported values: profile, email, phone, address |
| 5 | state | ✅ Required | Random string to maintain request integrity and prevent CSRF. Returned as-is in the callback. |
| 6 | nonce | Optional | Required if id_token is part of response_type. Associates the client session with the ID token to prevent replay attacks. |
| 7 | response_mode | Optional | Controls how the response parameters are returned. query (default for code flow), fragment, or form_post |
| 8 | prompt | Optional | login — forces re-authentication. none — no UI shown; returns error if user is not already authenticated. |
| 9 | display | Optional | Controls how the login UI is displayed. page (default) or popup. Client must implement popup support if required. |
| 10 | id_token_hint | Optional | A previously issued ID token hinting the current user. Returns a positive response if the user matches; otherwise returns login_required. |
| 11 | login_hint | Optional | Hint to pre-fill the login identifier (email or phone). Returns login_required if the active session doesn't match. |
| 12 | max_age | Optional | Maximum allowed elapsed time (in seconds) since the user's last active authentication. Triggers re-authentication if exceeded. Forces auth_time claim in the ID token. |
| 13 | acr_values | Optional | Set to loginradius:nist:level:1:re-auth to force re-authentication regardless of existing session. Value is returned in the acr claim of the ID token. |
| 14 | ui_locales | Optional | Preferred UI languages as a space-separated BCP47 list. Example: fr-CA fr en |
| 15 | claims | Optional | JSON object to request specific claims in the id_token or at the userinfo endpoint. |
Token Request Parameters
| Parameter | Required | Description |
|---|---|---|
client_id | ✅ Required | Your OIDC application clientId |
client_secret | ✅ Required (non-PKCE) | Your OIDC application ClientSecret. Not required for PKCE flows. |
grant_type | ✅ Required | Must be authorization_code |
code | ✅ Required | The authorization code received from the callback |
redirect_uri | ✅ Required | Must exactly match the redirect_uri used in the authorization request |
code_verifier | ✅ Required (PKCE) | The original code verifier whose hash matches the code_challenge sent in the authorization request |
Token Response Fields
| Field | Description |
|---|---|
access_token | LoginRadius JWT — use this to call protected APIs |
token_type | Always Bearer |
expires_in | Lifetime of the access token in seconds |
refresh_token | Long-lived token to obtain new access tokens after expiry |
id_token | JWT containing identity claims about the authenticated user |
Scope to Claims Mapping
| Scope | Claims Returned |
|---|---|
openid | sub (required baseline) |
profile | name, given_name, family_name, birthdate, picture, gender, website, etc. |
email | email, email_verified |
phone | phone_number, phone_number_verified |
address | address (structured claim - street_address, locality, region, postal_code, country) |
Using with Identity Orchestration
For a full walkthrough covering configuration steps, use cases (MFA, custom claims, progressive profiling), and complete URL parameter reference, see OIDC/OAuth Flows with Identity Orchestration.