Instantly share code, notes, and snippets.
Forked from Armstrong2035/AuthorizeSpotifyUser.js
Created
June 16, 2024 22:31
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
-
Save Uvacoder/674d9e157b7ba7dbcbf21ad7af5f3dfb to your computer and use it in GitHub Desktop.
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
| import React, { useState, useEffect } from "react"; | |
| const clientId = "b841fe980d704720934f655f5e92d2e3"; | |
| const redirectUrl = "http://localhost:3000/callback"; | |
| const authorizationEndpoint = "https://accounts.spotify.com/authorize"; | |
| const tokenEndpoint = "https://accounts.spotify.com/api/token"; | |
| const scope = | |
| "user-read-private user-read-email playlist-read-private playlist-modify-private user-library-read user-library-modify"; | |
| function SpotifyLogin() { | |
| const [currentToken, setCurrentToken] = useState({ | |
| access_token: localStorage.getItem("access_token") || null, | |
| refresh_token: localStorage.getItem("refresh_token") || null, | |
| expires_in: localStorage.getItem("expires_in") || null, | |
| expires: localStorage.getItem("expires") || null, | |
| }); | |
| const generateRandomString = () => { | |
| const possible = | |
| "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; | |
| const randomValues = crypto.getRandomValues(new Uint8Array(64)); | |
| const randomValue = randomValues.reduce( | |
| (acc, x) => acc + possible[x % possible.length], | |
| "" | |
| ); | |
| return randomValue; | |
| }; | |
| const generateCodeChallenge = async (codeVerifier) => { | |
| const hashed = await crypto.subtle.digest( | |
| "SHA-256", | |
| new TextEncoder().encode(codeVerifier) | |
| ); | |
| return btoa(String.fromCharCode(...new Uint8Array(hashed))) | |
| .replace(/=/g, "") | |
| .replace(/\+/g, "-") | |
| .replace(/\//g, "_"); | |
| }; | |
| const redirectToSpotifyAuthorize = async () => { | |
| const codeVerifier = generateRandomString(); | |
| localStorage.setItem("code_verifier", codeVerifier); | |
| alert(codeVerifier); | |
| const codeChallenge = await generateCodeChallenge(codeVerifier); | |
| console.log(codeChallenge); | |
| const authUrl = new URL(authorizationEndpoint); | |
| authUrl.search = new URLSearchParams({ | |
| response_type: "code", | |
| client_id: clientId, | |
| scope: scope, | |
| code_challenge_method: "S256", | |
| code_challenge: codeChallenge, | |
| redirect_uri: redirectUrl, | |
| }).toString(); | |
| console.log(authUrl); | |
| return authUrl; | |
| // ?response_type=code&client_id=b841fe980d704720934f655f5e92d2e3&scope=user-read-private+user-read-email+playlist-read-private+playlist-modify-private+user-library-read+user-library-modify&code_challenge_method=S256&code_challenge=0QxO8vQzlcAOCmPOBSbXxLt_EqkUxJ52p-OsDq4DjTY&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback | |
| // Redirect the user to the Spotify authorization page | |
| window.location.href = authUrl.toString(); | |
| // Log the authorization code when the user is redirected back to your application | |
| const handleRedirect = () => { | |
| const params = new URLSearchParams(window.location.search); | |
| const code = params.get("code"); | |
| console.log(params, code); | |
| if (code) { | |
| console.log("Authorization Code:", code); | |
| } | |
| }; | |
| // Attach the handleRedirect function to window's onload event to execute it when the page loads after redirection | |
| window.onload = handleRedirect; | |
| }; | |
| const getToken = async (code) => { | |
| const codeVerifier = localStorage.getItem("code_verifier"); | |
| const response = await fetch(tokenEndpoint, { | |
| method: "POST", | |
| headers: { | |
| "Content-Type": "application/x-www-form-urlencoded", | |
| }, | |
| body: new URLSearchParams({ | |
| client_id: clientId, | |
| grant_type: "authorization_code", | |
| code: code, | |
| redirect_uri: redirectUrl, | |
| code_verifier: codeVerifier, | |
| }), | |
| }); | |
| return response.json(); | |
| }; | |
| const saveToken = (token) => { | |
| localStorage.setItem("access_token", token.access_token); | |
| localStorage.setItem("refresh_token", token.refresh_token); | |
| localStorage.setItem("expires_in", token.expires_in); | |
| const now = new Date(); | |
| const expiry = new Date(now.getTime() + token.expires_in * 1000); | |
| localStorage.setItem("expires", expiry); | |
| setCurrentToken(token); | |
| }; | |
| useEffect(() => { | |
| const fetchData = async () => { | |
| const code = new URLSearchParams(window.location.search).get("code"); | |
| if (code) { | |
| const token = await getToken(code); | |
| saveToken(token); | |
| window.history.replaceState( | |
| {}, | |
| document.title, | |
| window.location.pathname | |
| ); // Remove code from URL | |
| } | |
| }; | |
| fetchData(); | |
| }, []); | |
| // useEffect(() => { | |
| // if (currentToken.access_token) { | |
| // getUserData().then((userData) => { | |
| // // Render logged-in template with user data | |
| // console.log("User Data:", userData); | |
| // }); | |
| // } | |
| // }, [currentToken.access_token]); | |
| const refreshToken = async () => { | |
| const response = await fetch(tokenEndpoint, { | |
| method: "POST", | |
| headers: { | |
| "Content-Type": "application/x-www-form-urlencoded", | |
| }, | |
| body: new URLSearchParams({ | |
| client_id: clientId, | |
| grant_type: "refresh_token", | |
| refresh_token: currentToken.refresh_token, | |
| }), | |
| }); | |
| return response.json(); | |
| }; | |
| const getUserData = async () => { | |
| const response = await fetch("https://api.spotify.com/v1/me", { | |
| method: "GET", | |
| headers: { Authorization: "Bearer " + currentToken.access_token }, | |
| }); | |
| return response.json(); | |
| }; | |
| const logoutClick = () => { | |
| localStorage.clear(); | |
| window.location.href = redirectUrl; | |
| }; | |
| const refreshTokenClick = async () => { | |
| const token = await refreshToken(); | |
| saveToken(token); | |
| }; | |
| return ( | |
| <div> | |
| {currentToken.access_token ? ( | |
| <div> | |
| <h1>User is logged in</h1> | |
| <button onClick={logoutClick}>Logout</button> | |
| <button onClick={refreshTokenClick}>Refresh Token</button> | |
| </div> | |
| ) : ( | |
| <div> | |
| <h1>User is not logged in</h1> | |
| <button onClick={redirectToSpotifyAuthorize}> | |
| Login with Spotify | |
| </button> | |
| </div> | |
| )} | |
| </div> | |
| ); | |
| } | |
| export default SpotifyLogin; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment