I figured out the authorization code expires right after being used and becomes obsolete after one use only. The flow is working well just after the autorization prompt, but when you reload the page if you stored the returned "code" like Spotify documentation suggests.
So my workaround is to store an info "post_authorization" and to rather store the access_token instead of the user code.
- If True, we generate a token based on the "code" we get from window.location
- If False, either we already have an access_token and we can go to the next step, either we don't and we need another authorization
const appClientId = "your client id";
const redirectUri = 'http://localhost:5173/callback';
const accessToken = localStorage.getItem("access_token");
var postAuthorization = localStorage.getItem("post_authorization")
console.log("postAuthorization: " + postAuthorization)
console.log("accessToken: " + accessToken)
if ((!accessToken || accessToken === 'undefined') && (!postAuthorization || postAuthorization === 'no')) {
console.log("Auth flow");
localStorage.setItem('post_authorization', 'yes')
redirectToAuthCodeFlow(appClientId);
} else if (postAuthorization === 'yes') {
console.log("Post Auth flow");
const params = new URLSearchParams(window.location.search);
const userCode = params.get("code");
const accessToken = await getAccessToken(appClientId, userCode);
localStorage.setItem('access_token', accessToken); // Store the access token
console.log("accessToken is saved to "+accessToken)
let postAuthorization = 'no';
localStorage.setItem('post_authorization', "no"); // Can now connect directly with the access token
const profile = await fetchProfile(accessToken);
populateUI(profile);
} else {
console.log("Post Access Token");
const profile = await fetchProfile(accessToken);
populateUI(profile);
}