The OAuth code flow allows you to obtain an authorization code and exchange it for an access token. This process involves generating an authorization URL, redirecting the user, and then exchanging the code for tokens.
Step 1: Generate Authorization URL
To get an authorization code, you need to generate an authorization URL. This URL will redirect you to the Credenza API.
Begin by generating a random string for the code verifier:
const verifier = generateRandomString(128)
const verifierHashed = await sha256(verifier)
const codeChallenge = base64urlencode(verifierHashed)
Generate state and nonce values:
const state = generateRandomString(32)
const nonce = generateRandomString(32)
Save verifier, state, and nonce for later use:
localStorage.setItem('oauth_verifier', verifier)
localStorage.setItem('oauth_state', state)
localStorage.setItem('oauth_nonce', nonce)
Form the redirect URI:
const redirectUri = `${window.location.origin}/auth/callback`
Create the authorization URL:
const authUrl = new URL(`${VITE_CREDENZA_OAUTH_URI}/oauth2/authorize`)
authUrl.searchParams.set('client_id', VITE_CLIENT_ID)
authUrl.searchParams.set('scope', 'offline.access openid profile profile.write email phone blockchain.evm.write blockchain.evm')
authUrl.searchParams.set('nonce', nonce)
authUrl.searchParams.set('response_type', 'code')
authUrl.searchParams.set('redirect_uri', redirectUri)
authUrl.searchParams.set('state', state)
authUrl.searchParams.set('code_challenge_method', 'S256')
authUrl.searchParams.set('code_challenge', codeChallenge)
Redirect the user to the authorization page:
window.location.href = authUrl.toString()
Step 2: Exchange Authorization Code for Tokens
Once you have received the authorization code, you can exchange it for tokens.
Extract the code and state from the URL parameters:
const urlParams = new URLSearchParams(window.location.search)
const code = urlParams.get('code')
const state = urlParams.get('state')
Verify the state parameter:
const savedState = localStorage.getItem('oauth_state')
if (state !== savedState) {
throw new Error('Invalid state parameter')
}
Get the saved verifier:
const codeVerifier = localStorage.getItem('oauth_verifier')
if (!codeVerifier) {
throw new Error('No verifier found')
}
Form the URL-encoded data:
const redirectUri = `${window.location.origin}/auth/callback`
const urlEncoded = new URLSearchParams({
grant_type: 'authorization_code',
client_id: clientId,
client_secret: clientSecret,
code: code,
code_verifier: codeVerifier,
redirect_uri: redirectUri,
})
Send a POST request to exchange the code for tokens:
const response = await fetch(`${API}/oauth2/token`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: urlEncoded.toString(),
})
if (!response.ok) {
throw new UnauthorizedException('Cannot exchange code for token')
}
const json = (await response.json()) as {
access_token: string
refresh_token: string
id_token: string
}
return {
accessToken: json.access_token,
refreshToken: json.refresh_token,
idToken: json.id_token,
}
For more information about the PKCE flow, refer to the standard documentation.