Skip to main content

OAuth2 Authorization Flow

This guide walks through the complete OAuth2 authorization code flow with PKCE, which is the recommended approach for user-facing applications.

Step 1: Generate PKCE parameters

Before redirecting the user, generate a code verifier and challenge:

const crypto = require('crypto');

// Generate a random code verifier (43-128 characters)
const codeVerifier = crypto.randomBytes(32).toString('base64url');

// Create the code challenge (S256)
const codeChallenge = crypto
.createHash('sha256')
.update(codeVerifier)
.digest('base64url');

Step 2: Redirect to authorization endpoint

Direct the user's browser to the authorization endpoint:

GET https://api.data.jlr-vcdp.com/auth?
response_type=code&
client_id=YOUR_CLIENT_ID&
redirect_uri=https://your-app.com/callback&
scope=vehicle:read charger:read&
state=RANDOM_STATE_VALUE&
code_challenge=CODE_CHALLENGE&
code_challenge_method=S256

The user will authenticate with the IdP and grant consent for the requested scopes.

Step 3: Handle the callback

After consent, the IdP redirects back to your redirect_uri with an authorization code:

https://your-app.com/callback?code=AUTH_CODE&state=RANDOM_STATE_VALUE

Verify the state parameter matches what you sent to prevent CSRF attacks.

Step 4: Exchange code for tokens

Exchange the authorization code for an access token. Include a DPoP proof header:

curl -X POST https://api.data.jlr-vcdp.com/auth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "DPoP: YOUR_DPOP_PROOF_JWT" \
-d "grant_type=authorization_code" \
-d "client_id=YOUR_CLIENT_ID" \
-d "code=AUTH_CODE" \
-d "redirect_uri=https://your-app.com/callback" \
-d "code_verifier=CODE_VERIFIER"

Step 5: Receive tokens

A successful response returns:

{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "DPoP",
"expires_in": 300,
"refresh_token": "eyJhbGciOiJSUzI1NiIs...",
"refresh_expires_in": 1800,
"scope": "vehicle:read charger:read"
}

Refreshing tokens

When the access token expires, use the refresh token to obtain a new one:

curl -X POST https://api.data.jlr-vcdp.com/auth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "DPoP: YOUR_DPOP_PROOF_JWT" \
-d "grant_type=refresh_token" \
-d "client_id=YOUR_CLIENT_ID" \
-d "refresh_token=YOUR_REFRESH_TOKEN"

Client credentials flow

For server-to-server integrations without user interaction:

curl -X POST https://api.data.jlr-vcdp.com/auth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "DPoP: YOUR_DPOP_PROOF_JWT" \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "scope=vehicle:read"

Next steps