Created
November 13, 2023 14:23
-
-
Save Lauro235/bb6a21f90edb6f2cc8bb7851c381ce16 to your computer and use it in GitHub Desktop.
Spotify PKCE
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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