Unlock a world of possibilities! Login now and discover the exclusive benefits awaiting you.
Hi Qlik Community,
I’m working on implementing OAuth2 Authorization Code Flow with PKCE in a React SPA for Qlik Cloud, but I’m running into a 401 error when attempting to exchange my authorization code for tokens.
Error Response
When I POST to /oauth/token, I receive:
Code Snippet
Here is my token-exchange function using axios:
Hey @AyeshaChhapra , I'm seeing two missing things here.
First, which could not cause the issue, you are missing "scope" parameter in the /oauth/token body request. You can use "user_default", but it depends on your requirements.
Second, which could cause the issue, you are missing "credentaials": "include" in the /oauth/token request. When you are redirected you should have some technical cookies and have to be attached.
Below my code which is working correctly:
const oAuthTokenRequestBody = {
"grant_type": "authorization_code",
"scope": "user_default",
"code": oAuthCode,
"redirect_uri": "https://localhost:8080/oauth_callback_custom.html",
"code_verifier": localStorage.getItem('codeVerifier'),
"client_id": "_clientId_"
}
const oAuthTokenRequest = await fetch('https://_tenant_.qlikcloud.com/oauth/token', {
method: 'POST',
body: JSON.stringify(oAuthTokenRequestBody),
credentials: "include",
headers: {
"content-type": "application/json"
}
})
Hi there!
A 401 "Unauthorized" error (code "OAUTH-5") during the token exchange step of the OAuth2 Authorization Code Flow with PKCE typically indicates an issue with the credentials or parameters being sent to the /oauth/token endpoint. Given your code snippet and the error, here's a breakdown of common causes and how to troubleshoot them:
Common Causes for OAUTH-5 (401 Unauthorized)
Incorrect client_id: This is a very frequent culprit. Double-check that import.meta.env.VITE_QLIK_CLIENT_ID exactly matches the Client ID you obtained when registering your SPA in Qlik Cloud. Any typo or mismatch will lead to a 401.
Mismatched redirect_uri: The redirect_uri sent in the token exchange request (import.meta.env.VITE_REDIRECT_URI) must precisely match the redirect_uri that was used in the initial authorization request and, crucially, the redirect_uri configured for your client in Qlik Cloud. Even a trailing slash difference can cause this error.
Invalid code: The authorization code you received from the authorization server is single-use and has a short lifespan.
Expired Code: If there's a significant delay between getting the code and exchanging it, it might have expired.
Used Code: If you're trying to exchange the same code multiple times (e.g., due to a page refresh or re-rendering), it will be invalid after the first successful exchange.
Mismatched code_verifier: The code_verifier sent in the token exchange must exactly match the original code_verifier that was used to generate the code_challenge for the initial authorization request.
Storage Issue: Ensure sessionStorage.getItem("pkce_verifier") is correctly retrieving the exact verifier that was stored. Any modification, truncation, or failure to retrieve it will cause a mismatch.
Timing: The verifier should be stored before redirecting to the authorization endpoint.
Incorrect Content-Type Header: While your code snippet correctly sets "Content-Type": "application/x-www-form-urlencoded", it's worth double-checking that no other part of your application or any proxy is inadvertently changing this. The body being a URLSearchParams object is correct for this content type.
Qlik Cloud Application Configuration:
PKCE Enabled: Ensure that your OAuth client in Qlik Cloud is configured to use PKCE. While the code_verifier implies you're attempting to use it, the server-side configuration needs to align.
marykayintouch
Grant Types: Verify that "Authorization Code" is an allowed grant type for your client in Qlik Cloud.
Hey @AyeshaChhapra , I'm seeing two missing things here.
First, which could not cause the issue, you are missing "scope" parameter in the /oauth/token body request. You can use "user_default", but it depends on your requirements.
Second, which could cause the issue, you are missing "credentaials": "include" in the /oauth/token request. When you are redirected you should have some technical cookies and have to be attached.
Below my code which is working correctly:
const oAuthTokenRequestBody = {
"grant_type": "authorization_code",
"scope": "user_default",
"code": oAuthCode,
"redirect_uri": "https://localhost:8080/oauth_callback_custom.html",
"code_verifier": localStorage.getItem('codeVerifier'),
"client_id": "_clientId_"
}
const oAuthTokenRequest = await fetch('https://_tenant_.qlikcloud.com/oauth/token', {
method: 'POST',
body: JSON.stringify(oAuthTokenRequestBody),
credentials: "include",
headers: {
"content-type": "application/json"
}
})