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
- DPoP Implementation — How to create the DPoP proof JWT