Skip to main content

Refresh Token Grant

The Refresh Token grant allows applications to obtain new access tokens without requiring the user to re-authenticate. This is essential for maintaining long-lived sessions while keeping access tokens short-lived for security.

Overview of Refresh Token Grant

Refresh tokens are long-lived credentials issued alongside access tokens during the initial authorization. When an access token expires, the application can use the refresh token to obtain a new access token without user interaction, providing a seamless experience.

Use Cases:

  • Long-lived Sessions: Keep users logged in for days or weeks without requiring re-authentication
  • Mobile Applications: Maintain authentication across app restarts and background states
  • Single-Page Applications: Silently refresh expired tokens without disrupting the user experience
  • Desktop Applications: Allow users to remain authenticated between sessions
  • Background Sync: Enable periodic data synchronization even when the user is not actively using the app

Why Use Refresh Tokens: Access tokens are intentionally short-lived (typically 1 hour) to limit the impact of token theft. Refresh tokens allow applications to obtain fresh access tokens without forcing users to log in repeatedly, balancing security with usability.

Key Benefits:

  • Improved Security: Short-lived access tokens reduce the window of opportunity for token misuse
  • Seamless User Experience: Users stay logged in without frequent re-authentication
  • Revocable: Refresh tokens can be revoked server-side to immediately terminate access
  • Rotation Support: Refresh tokens can be rotated on each use for enhanced security
  • Offline Access: Some systems allow refresh tokens to work even when the user is offline

Refresh Token Flow

Flow Steps in Detail

Step 1: Obtaining a Refresh Token

Refresh tokens are issued during the Authorization Code Grant with PKCE flow when you include the offline_access scope:

Authorization Request (include offline_access):

GET /w/{tenant}/oauth/api/v1/authorize?
response_type=code&
client_id=your-app-id&
redirect_uri=https://yourapp.com/callback&
scope=openid+profile+email+offline_access+patient/*.read&
state=random-state&
code_challenge=SHA256_CHALLENGE&
code_challenge_method=S256

Key Parameters:

  • offline_access - Required to receive a refresh token
  • code_challenge - Required PKCE challenge for security
  • code_challenge_method=S256 - Required SHA-256 hash method

Token Exchange Request:

POST /w/{tenant}/oauth/api/v1/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&
code=AUTH_CODE&
redirect_uri=https://yourapp.com/callback&
client_id=your-app-id&
code_verifier=ORIGINAL_VERIFIER

Token Response (with refresh token):

{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"scope": "openid profile email offline_access patient/*.read",
"id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Important: Refresh tokens are only issued when:

  • Authorization Code Grant with PKCE: Yes, when offline_access scope is requested
  • User grants offline access permission: Yes, if consent screen is shown
  • Client Credentials Grant: No (request new token instead)
  • Without offline_access scope: No refresh token issued

Step 2: Storing the Refresh Token

Store refresh tokens securely based on your application type.

Step 3: Using the Refresh Token

When the access token expires, exchange the refresh token for a new access token:

Request:

POST /w/{tenant}/oauth/api/v1/token HTTP/1.1
Host: api.haste.health
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&
refresh_token=REFRESH_TOKEN_HERE&
client_id=your-client-id

For Confidential Clients (with client_secret):

POST /w/{tenant}/oauth/api/v1/token HTTP/1.1
Host: api.haste.health
Content-Type: application/x-www-form-urlencoded
Authorization: Basic base64(client_id:client_secret)

grant_type=refresh_token&
refresh_token=REFRESH_TOKEN_HERE

Parameters:

ParameterRequiredDescription
grant_typeYesMust be refresh_token
refresh_tokenYesThe refresh token received from the initial authorization
client_idYesYour application's client identifier
scopeOptionalRequested scopes (must be subset of original scopes)

Step 4: Refresh Token Response

With Rotation (New Refresh Token):

{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"scope": "openid profile email patient/*.read"
}

Note: Refresh token rotation is enabled by default, the old refresh token is invalidated and a new one is issued.

Refresh Token Rotation

Refresh token rotation is a security best practice where each refresh token is single-use. After using a refresh token, it's invalidated and a new one is issued.

Error Handling

Token Refresh Errors

Error CodeDescriptionResolution
invalid_grantRefresh token is invalid, expired, or revokedClear tokens and redirect to login
invalid_clientClient authentication failedVerify client_id (and client_secret if confidential)
invalid_requestMissing or malformed required parameterCheck grant_type and refresh_token parameters
unauthorized_clientClient not authorized to use refresh tokensContact administrator to enable refresh tokens
unsupported_grant_typeServer doesn't support refresh_token grantUse grant_type=refresh_token

Example Error Response

{
"error": "invalid_grant",
"error_description": "The refresh token has expired or been revoked",
"error_uri": "https://api.haste.health/errors/invalid_grant"
}

Comparison with Other Flows

FeatureRefresh TokenAuthorization CodeClient Credentials
PurposeRenew access tokensInitial user loginM2M authentication
User InteractionNoneRequiredNone
Requires Initial AuthYesN/A (is initial auth)No
Token LifetimeLong (days/weeks)Short (minutes)N/A
Can Be RevokedYesN/AYes (revoke access token)
Rotation SupportedYes (recommended)N/AN/A
Best ForLong sessionsFirst-time authService accounts

Resources