Refresh Token Flow
A refresh_token is a long-lived credential issued alongside the access_token during a successful authentication. It allows the client to obtain a new access_token — and a new refresh_token — without requiring the user to re-authenticate, as long as the refresh token is valid and has not been revoked.
This page covers the end-to-end refresh token flow as implemented by LoginRadius, including the token request, rotation behaviour, and the optional Overlap Window (ReuseInterval) that adds replay-safe reliability for clients on unreliable networks.
Overview
The refresh token flow operates entirely as a back-channel call — no browser interaction or user login is required:
- The client detects that the
access_tokenhas expired (or is about to expire). - The client makes a direct
POSTrequest to the LoginRadius Token endpoint withgrant_type=refresh_tokenand the storedrefresh_token. - LoginRadius validates the token and, if valid, issues a new
access_token,refresh_token, andid_token. - The old
refresh_tokenis immediately invalidated — this is refresh token rotation, and it is always active on LoginRadius.
Flow Diagram
Step-by-Step Walkthrough
Step 1 — Detect Token Expiry
The client should proactively check whether the access_token is nearing expiry using the expires_in value returned during the original authentication or a prior refresh. Waiting for a 401 Unauthorized from a protected API is also a valid trigger.
Best practice: Refresh the
access_tokenslightly beforeexpires_inelapses (e.g., 60 seconds before), rather than waiting for an API call to fail. This avoids latency-sensitive failures in production.
Step 2 — Token Refresh Request
The client makes a direct POST call to the LoginRadius Token endpoint. This call never goes through the browser.
Endpoint
POST https://{SiteURL}/api/oidc/{OIDCAppName}/token
SiteURL= Either<TenantName>.hub.loginradius.comor a Custom Domain i.e.auth.your-app.com.OIDCAppName= your configured OIDC App name.
The token endpoint accepts application/x-www-form-urlencoded as the content type for refresh token requests.
Client Secret Post
Client Secret Basic
The client_id and client_secret are included directly in the request body.
POST /api/oidc/{OIDCAppName}/token
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token
&refresh_token={your_refresh_token}
&client_id=YOUR_OIDC_CLIENT_ID
&client_secret=YOUR_OIDC_CLIENT_SECRET
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.
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=refresh_token
&refresh_token={your_refresh_token}
Step 3 — Token Validation
LoginRadius validates the incoming refresh token against the following conditions. If any check fails, a 400 invalid_grant is returned and the client must initiate a new authentication flow.
| Validation | Description |
|---|---|
| Token exists | The refresh token is present in the token store |
| Token not expired | The refresh token has not exceeded its configured TTL |
| Token not revoked | The token has not been explicitly revoked via a logout or revocation call |
| Token not already used | The token has not been used in a prior rotation cycle (subject to ReuseInterval — see below) |
| Client match | The client_id in the request matches the client_id the token was issued for |
Step 4 — Token Issuance & Rotation
Upon successful validation, LoginRadius:
- Invalidates the old
refresh_token— it can no longer be used for subsequent refreshes. - Issues a new token set — a new
access_token,refresh_token, andid_token. - Returns the new tokens to the client.
The client must replace its stored token pair with the newly returned tokens immediately.
Success Response
{
"access_token": "<New LoginRadius JWT Access Token>",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "<New Refresh Token>",
"id_token": "<New JWT ID Token>"
}
Error Response
{
"error": "invalid_grant",
"error_description": "The refresh_token is not valid",
}
Token Request Parameters
| Parameter | Required | Description |
|---|---|---|
grant_type | ✅ Required | Must be refresh_token |
refresh_token | ✅ Required | The refresh token issued during the previous authentication or refresh |
client_id | ✅ Required | Your OIDC application client_id |
client_secret | ✅ Required (confidential clients) | Your OIDC application client_secret. Not required for PKCE / public clients. |
Token Response Fields
| Field | Description |
|---|---|
access_token | New LoginRadius JWT — use this to call protected APIs |
token_type | Always Bearer |
expires_in | Lifetime of the new access token in seconds |
refresh_token | New refresh token — replace the old one immediately |
id_token | JWT containing updated identity claims about the authenticated user |
Refresh Token Rotation
LoginRadius enforces refresh token rotation on every use. Each time a refresh token is used, it is invalidated and a new token pair is issued in its place. This limits the damage window if a refresh token is stolen — any replay of the old token will fail because it has already been cycled.
Important: Always replace the stored
refresh_tokenwith the newly issued one before making any subsequent API calls. Holding onto a used token is the most common cause ofinvalid_granterrors.
Refresh Token Rotation with Overlap Window (ReuseInterval)
Standard rotation creates a reliability problem on unreliable networks: if LoginRadius rotates the token but the network drops the response before the client receives it, the client retries with the now-invalidated original token and receives a permanent invalid_grant — forcing a full re-authentication even though nothing went wrong.
The Overlap Window (ReuseInterval) solves this by allowing the same refresh token to be safely replayed within a short, configurable grace period. During this window, LoginRadius recognises the replay and returns the same token set that was issued on the first use. After the window expires, the token is permanently rejected and full rotation security is restored.
How the Overlap Window Works
- The client sends a refresh request with
RT1. - LoginRadius validates
RT1and issues a new token pair (AT2,RT2,IDT2). RT1is now used. For the duration ofReuseInterval, LoginRadius still recognizesRT1as a valid replay rather than rejecting it outright.- If the network drops the response: the client retries with
RT1. LoginRadius recognizes the replay and returns the sameAT2,RT2,IDT2with a recalculatedexpires_in. The response is idempotent. - Once
ReuseIntervalelapses,RT1is no longer recognized. Any further replay ofRT1returns400 invalid_grant.
Configuration
ReuseInterval is set on the OIDC application's OAuth configuration under Refresh Token Rotation section:
| Field | Type | Default | Valid Range | Description |
|---|---|---|---|---|
ReuseInterval | integer | 0 | 0–60 seconds | Grace period during which a used refresh token can be safely replayed. 0 disables the overlap window and standard single-use rotation applies. |
Recommendation: Set
ReuseIntervalbetween 5 and 30 seconds — long enough to absorb a network-level retry, short enough to minimise the window in which a stolen token could be replayed. Values outside0–60are rejected at configuration time.
Overlap Window Behaviour Reference
| Scenario | ReuseInterval | Outcome |
|---|---|---|
| First use of a refresh token | Any | New token pair issued; old token marked as used |
| Replay within the overlap window | > 0 | Same token pair returned (idempotent); expires_in recalculated |
| Replay after the overlap window expires | > 0 | 400 invalid_grant |
| Any replay | 0 (disabled) | 400 invalid_grant |
| Explicit token revocation, then replay | Any | 400 invalid_grant |
Security Properties of the Overlap Window
Enabling ReuseInterval does not weaken rotation security in meaningful ways, but the following properties should be understood:
| Property | Behaviour |
|---|---|
| Stolen token replayed within the window | The attacker and the legitimate client receive the same token set. The next rotation cycle will detect divergence if the attacker attempts to use the received tokens. |
| Stolen token replayed after the window expires | Rejected — 400 invalid_grant. Full rotation security applies. |
| Explicit revocation | The token is rejected immediately, even if it is still within its ReuseInterval window. |
ReuseIntervalmust always be significantly smaller than the refresh token TTL to preserve the security properties of rotation.