Skip to main content

Authorization Code Grant

For the authorization code grant flow we require PKCE (Proof Key for Code Exchange).

Overview with of Authorization code grant with PKCE (Proof Key for Code Exchange)

A highly secure flow in the OAuth 2.0 framework. It enhances the standard Authorization Code flow, primarily to protect public clients (like mobile and single-page applications) that cannot securely store a client_secret

Use Cases:

  • Native Mobile Applications: Clients (iOS, Android apps) that cannot securely store a traditional, static client_secret within their distributed code.
  • Single-Page Applications (SPAs): Client-side JavaScript applications running in a browser that are vulnerable to code inspection, making them unable to secure a static client_secret.
  • Desktop Applications: Applications running on an end-user's machine, which are also considered public clients for security purposes.
  • Confidential Clients (Web Apps with a Backend): Although they can use a client_secret, PKCE is still recommended as an extra layer of defense against certain types of code injection and CSRF attacks.

Key Benefits:

  • Prevents Code Interception Attacks An attacker who intercepts the authorization_code from the redirect URI cannot exchange it for an access token because they do not possess the secret code_verifier. This is the primary security benefit.
  • Eliminates Client Secret for Public Clients PKCE removes the need for public clients (like SPAs and Mobile apps) to register or use a static client_secret, solving the problem of insecure secret storage.
  • Mitigates Cross-Site Request Forgery (CSRF) By dynamically linking the initial authorization request to the final token exchange, PKCE provides strong protection against CSRF, often making the use of the state parameter redundant for this specific purpose.
  • Default Security Standard PKCE is now mandated in the OAuth 2.0 Security Best Current Practice and the upcoming OAuth 2.1 specification, making it the required flow for modern application development.

Authorization Code Flow with PKCE

Flow Steps in Detail

Step 1: Authorization Request

The client application redirects the user to the authorization endpoint with the following parameters:

Request:

GET /w/{tenant}/oauth/api/v1/authorize?
response_type=code&
client_id=your-client-id&
redirect_uri=https://yourapp.com/callback&
scope=openid+profile+email+patient/*.read&
state=random-state-value&
code_challenge=CHALLENGE&
code_challenge_method=S256 HTTP/1.1
Host: api.haste.health

Parameters:

ParameterRequiredDescription
response_typeYesMust be code for authorization code flow
client_idYesYour application's client identifier
redirect_uriYesWhere to redirect after authorization (must be pre-registered)
scopeYesSpace-delimited list of requested scopes (must include openid for OIDC)
stateRecommendedRandom value to prevent CSRF attacks
code_challengeRequiredPKCE code challenge (SHA-256 hash of code_verifier)
code_challenge_methodRequiredMust be S256 (SHA-256 hash method)
nonceOptionalRandom value included in ID token to prevent replay attacks
promptOptionalnone, login, consent, or select_account
max_ageOptionalMaximum authentication age in seconds

Step 2: User Authentication

The authorization server authenticates the user through:

  1. Login form (username/password, MFA)
  2. Session cookie (if already logged in)
  3. Federated identity provider (SSO)

If required, the authorization server displays a consent screen showing:

  • Application name and description
  • Requested scopes and permissions
  • Option to approve or deny

Step 4: Authorization Code Generation

Upon successful authentication and consent, the authorization server:

  1. Generates a short-lived authorization code (typically 1-10 minutes)
  2. Associates the code with the client, user, and requested scopes
  3. Redirects back to the client's redirect URI

Response:

HTTP/1.1 302 Found
Location: https://yourapp.com/callback?
code=AUTH_CODE_HERE&
state=random-state-value

Step 5: Token Exchange

The SPA exchanges the authorization code for tokens using the code_verifier (no client_secret needed for public clients):

Request:

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

grant_type=authorization_code&
code=AUTH_CODE_HERE&
redirect_uri=https://yourapp.com/callback&
client_id=spa-client-id&
code_verifier=ORIGINAL_VERIFIER

Parameters:

ParameterRequiredDescription
grant_typeYesMust be authorization_code
codeYesThe authorization code received from callback
redirect_uriYesMust exactly match the original redirect URI
client_idYesYour SPA's registered client identifier
code_verifierRequiredThe original random string used to generate code_challenge (retrieved from sessionStorage)

Response:

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

Step 6: Access Protected Resources

Use the access token to call protected APIs:

Request:

GET /w/{tenant}/{project}/api/v1/fhir/r4/Patient/123 HTTP/1.1
Host: api.haste.health
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

Error Handling

Authorization Errors

Error CodeDescriptionResolution
invalid_requestMissing or invalid required parameterCheck all required parameters are included
unauthorized_clientClient not authorized for this grant typeVerify client configuration
access_deniedUser denied authorization requestInform user and allow retry
unsupported_response_typeAuthorization server doesn't support response typeUse response_type=code
invalid_scopeRequested scope is invalid or unknownCheck scope names and permissions
server_errorAuthorization server errorRetry with exponential backoff
temporarily_unavailableServer temporarily unavailableRetry after delay

Token Exchange Errors

Error CodeDescriptionResolution
invalid_requestMissing required parameterInclude all required parameters
invalid_clientClient authentication failedVerify client_id and client_secret
invalid_grantAuthorization code invalid, expired, or revokedRequest new authorization
unauthorized_clientClient not authorized for authorization code grantUpdate client configuration
unsupported_grant_typeGrant type not supportedUse grant_type=authorization_code

Example Error Response

{
"error": "invalid_grant",
"error_description": "The authorization code has expired or has already been used",
"error_uri": "https://api.haste.health/errors/invalid_grant"
}

Comparison with Other Flows

FeatureAuthorization Code + PKCEClient CredentialsImplicit (Deprecated)
Use CaseSPAs, mobile appsService-to-serviceSPAs (legacy)
Client SecretNot required (PKCE)RequiredNot possible
Refresh TokensYesOptionalNo
SecurityHighestHighLow
User ContextYesNoYes
PKCE Required✅ Yes❌ NoN/A
Recommended✅ Yes✅ Yes❌ No (use Auth Code + PKCE)

Resources