Skip to content

Instantly share code, notes, and snippets.

@Lauro235
Created November 13, 2023 14:23
Show Gist options
  • Save Lauro235/bb6a21f90edb6f2cc8bb7851c381ce16 to your computer and use it in GitHub Desktop.
Save Lauro235/bb6a21f90edb6f2cc8bb7851c381ce16 to your computer and use it in GitHub Desktop.
Spotify PKCE
const redirect = document.getElementById("redirect");
const token = document.getElementById("token");
const clientId = 'some_id';
const redirectUri = 'http://localhost:3000';
const authUrl = new URL("https://accounts.spotify.com/authorize")
const generateRandomString = (length) => {
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-~';
const values = crypto.getRandomValues(new Uint8Array(length));
return values.reduce((acc, x) => acc + possible[x % possible.length], "");
}
const codeChallenge = async (codeVerifier) => {
const sha256 = async (plain) => {
const encoder = new TextEncoder()
const data = encoder.encode(plain)
return window.crypto.subtle.digest('SHA-256', data)
}
const base64encode = (input) => {
return btoa(String.fromCharCode(...new Uint8Array(input)))
.replace(/=/g, '')
.replace(/\+/g, '-')
.replace(/\//g, '_');
}
const hashed = await sha256(codeVerifier);
const codeChallenge = base64encode(hashed);
return codeChallenge;
}
const spotifyRedirect = (codeVerifier, codeChallenge) => {
const scope = 'user-read-private user-read-email';
// generated in the previous step
window.localStorage.setItem('code_verifier', codeVerifier);
const params = {
response_type: 'code',
client_id: clientId,
scope,
code_challenge_method: 'S256',
code_challenge: codeChallenge,
redirect_uri: redirectUri,
}
authUrl.search = new URLSearchParams(params).toString();
window.location.href = authUrl.toString();
}
const getToken = async code => {
// stored in the previous step
let codeVerifier = localStorage.getItem('code_verifier');
const payload = {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
client_id: clientId,
grant_type: 'authorization_code',
code,
redirect_uri: redirectUri,
code_verifier: codeVerifier,
}),
}
const tokenUrl = new URL("https://accounts.spotify.com/authorize/api/token")
const body = await fetch(tokenUrl, payload);
const response = await body.json();
localStorage.setItem('access_token', response.access_token);
}
const codeVerifier = generateRandomString(64);
codeChallenge(codeVerifier);
const urlParams = new URLSearchParams(window.location.search);
let code = urlParams.get('code');
redirect.addEventListener("click", () => {
spotifyRedirect(codeVerifier, codeChallenge);
});
token.addEventListener("click", () => {
getToken(code);
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment