I wanted to get my hands dirty with Spotify’s Web API, and it seems that the first thing I need to get a hang of is Authorization. So, I cloned Spotify’s Web API Examples repository from github and opened it in vscode. I followed the instructions on the README and replaced the client id with the one I received from Spotify after I created an app through Spotify For Developers. I also replaced their Redirect URI with https://127.0.0.1:8080. After this, I ran npm install, and finally npm start. At this point, I saw the first part of the application run correctly, but after I pressed Log In with Spotify, I got redirected to a page that said “Invalid Client ID”. I looked at the url and realized that the client id it was looking for was the default: “yourClientIdGoesHere” rather than the updated client Id I had replaced it with.
I made sure the changes were saved to the file, and I tried restarting the server multiple times, but that did not work.
Here is what my app.js looks like. I made no other changes to files in the directory.
/**
* This is an example of a basic node.js script that performs
* the Authorization Code with PKCE oAuth2 flow to authenticate
* against the Spotify Accounts.
*
* For more information, read
* https://developer.spotify.com/documentation/web-api/tutorials/code-pkce-flow
*/
const clientId = 'ca93bf90292e4f13b9708468fbf516c0'; // your clientId
const redirectUrl = 'http://127.0.0.1:8080'; // your redirect URL - must be localhost URL and/or HTTPS
const authorizationEndpoint = "https://accounts.spotify.com/authorize";
const tokenEndpoint = "https://accounts.spotify.com/api/token";
const scope = 'user-read-private user-read-email';
// Data structure that manages the current active token, caching it in localStorage
const currentToken = {
get access_token() { return localStorage.getItem('access_token') || null; },
get refresh_token() { return localStorage.getItem('refresh_token') || null; },
get expires_in() { return localStorage.getItem('refresh_in') || null },
get expires() { return localStorage.getItem('expires') || null },
save: function (response) {
const { access_token, refresh_token, expires_in } = response;
localStorage.setItem('access_token', access_token);
localStorage.setItem('refresh_token', refresh_token);
localStorage.setItem('expires_in', expires_in);
const now = new Date();
const expiry = new Date(now.getTime() + (expires_in * 1000));
localStorage.setItem('expires', expiry);
}
};
// On page load, try to fetch auth code from current browser search URL
const args = new URLSearchParams(window.location.search);
const code = args.get('code');
// If we find a code, we're in a callback, do a token exchange
if (code) {
const token = await getToken(code);
currentToken.save(token);
// Remove code from URL so we can refresh correctly.
const url = new URL(window.location.href);
url.searchParams.delete("code");
const updatedUrl = url.search ? url.href : url.href.replace('?', '');
window.history.replaceState({}, document.title, updatedUrl);
}
// If we have a token, we're logged in, so fetch user data and render logged in template
if (currentToken.access_token) {
const userData = await getUserData();
renderTemplate("main", "logged-in-template", userData);
renderTemplate("oauth", "oauth-template", currentToken);
}
// Otherwise we're not logged in, so render the login template
if (!currentToken.access_token) {
renderTemplate("main", "login");
}
async function redirectToSpotifyAuthorize() {
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const randomValues = crypto.getRandomValues(new Uint8Array(64));
const randomString = randomValues.reduce((acc, x) => acc + possible[x % possible.length], "");
const code_verifier = randomString;
const data = new TextEncoder().encode(code_verifier);
const hashed = await crypto.subtle.digest('SHA-256', data);
const code_challenge_base64 = btoa(String.fromCharCode(...new Uint8Array(hashed)))
.replace(/=/g, '')
.replace(/+/g, '-')
.replace(///g, '_');
window.localStorage.setItem('code_verifier', code_verifier);
const authUrl = new URL(authorizationEndpoint)
const params = {
response_type: 'code',
client_id: 'ca93bf90292e4f13b9708468fbf516c0',
scope: scope,
code_challenge_method: 'S256',
code_challenge: code_challenge_base64,
redirect_uri: redirectUrl,
};
Would appreciate any help!



