使用 PKCE 流程从 Spotify 的 Web API 请求授权时遇到问题

问题描述 投票:0回答:0

我正在尝试使用 Spotify 的 Web API 为我的仅前端单页应用程序获取当前用户的播放列表,但控制台在尝试获取访问令牌时给我一个 400 错误,我认为这是一个语法错误代码。我正在使用 Spotify 的 PKCE 授权指南,但我不确定自己做错了什么。我可以毫无问题地访问 Spotify 的登录页面,但无法检索访问令牌。我确实注意到 VS Code 说 btoa(在 generateCodeChallenge 函数中使用)已被弃用,但我不确定在它的位置还可以使用什么。此外,当我尝试 console.log codeVerifier 变量时,它只记录 null(我认为这可能是由于 btoa 被弃用)。我认为这就是问题所在,但我不确定如何解决它。

这是我目前写的代码(我去掉了clientId和redirectUri):

const clientId = 
const redirectUri = 

function generateRandomString(length) {
    let text = '';
    let possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  
    for (let i = 0; i < length; i++) {
      text += possible.charAt(Math.floor(Math.random() * possible.length));
    }
    return text;
  }
  
  async function generateCodeChallenge(codeVerifier) {
    function base64encode(string) {
      return btoa(String.fromCharCode.apply(null, new Uint8Array(string)))
        .replace(/\+/g, '-')
        .replace(/\//g, '_')
        .replace(/=+$/, '');
    }
  
    const encoder = new TextEncoder();
    const data = encoder.encode(codeVerifier);
    const digest = await window.crypto.subtle.digest('SHA-256', data);
  
    return base64encode(digest);
  }

const Spotify = {
    login() {
        let codeVerifier = generateRandomString(128);

        generateCodeChallenge(codeVerifier).then(codeChallenge => {
          let state = generateRandomString(16);
          let scope = 'user-read-private user-read-email';

          localStorage.setItem('code-verifier', codeVerifier);

          let args = new URLSearchParams({
            response_type: 'code',
            client_id: clientId,
            scope: scope,
            redirect_uri: redirectUri,
            state: state,
            code_challenge_method: 'S256',
            code_challenge: codeChallenge
          });

          window.location = 'https://accounts.spotify.com/authorize?' + args;
        })
    },
    
    getAccessToken() {
      const urlParams = new URLSearchParams(window.location.search);
      let code = urlParams.get('code');

      let codeVerifier = localStorage.getItem('code_verifier');

      let body = new URLSearchParams({
        grant_type: 'authorization_code',
        code: code,
        redirect_uri: redirectUri,
        client_id: clientId,
        code_verifier: codeVerifier
      });

      fetch('https://accounts.spotify.com/api/token', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded'
          },
        body: body
        })
        .then(response => {
          if (!response.ok) {
            throw new Error('HTTP status ' + response.status);
          }
          return response.json();
        })
        .then(data => {
          localStorage.setItem('access-token', data.access_token);
        })
        .catch(error => {
          console.error('Error:', error);
        });      
    },

   async getPlaylists() {
    let accessToken = localStorage.getItem('access_token');
    const headers = {Authorization: 'Bearer ' + accessToken};

    const response = await fetch('https://api.spotify.com/v1/me/playlists?limit=20&offset=0', {headers: headers});
    const data = await response.json();
    const playlists = data.items;

    return playlists;
   }
}

export default Spotify;
javascript api asynchronous spotify
© www.soinside.com 2019 - 2024. All rights reserved.