【问题标题】:Spotify PKCE code_verifier was incorrectSpotify PKCE code_verifier 不正确
【发布时间】:2020-07-26 02:43:38
【问题描述】:

我很高兴听到我现在可以使用 Spotify Web API,而无需通过 PKCE 使用后端应用程序。不幸的是,我似乎有某种误解,无法让它发挥作用。

我可能在此过程中犯了一些小错误,但我做了一次无济于事,我擦干净石板并再次尝试,但仍然没有运气。由此我推测我一定是误解了documentation

我会解释我在做什么,希望这里的人能指出我遗漏了什么或做错了什么。我假设我有一个基本的概念误解。

我首先使用名为 crypto-random-string 的 npm 包生成一个加密随机字符串。我将其存储在浏览器的本地存储中,然后使用 js-sha256 对其进行哈希处理,然后使用另一个名为 base64url 的 npm 包对其进行编码。

    let verifier = cryptoRandomString({length: 50})
    window.localStorage.setItem('verifier', verifier)

    let params = {
      client_id: '[MY CLIENT ID]',
      response_type: 'code',
      redirect_uri: 'http://localhost:3000/callback',
      code_challenge_method: 'S256',
      code_challenge: base64url(sha256(verifier))
    }

    let endpoint = new URL('https://accounts.spotify.com/authorize');
    endpoint.search = new URLSearchParams(params);

    window.location = endpoint.toString();

从这里,我使用正确的 url 参数重定向到 /authorize 端点。我已经成功地做到了这一点,然后相应地被重定向到我提供的 redirect_uri,在那里我从 url 参数中获取给定的代码。

此时,我尝试使用 client_id、grant_type、我从 url 参数获得的代码、我的 redirect_uri 和本地存储的 code_verifier 获取 /api/token 端点。

    let params = new URLSearchParams(window.location.search);
    console.log(params.get('code'));

    let newParams = {
      client_id: '[MY CLIENT ID]',
      grant_type: 'authorization_code',
      code: params.get('code'),
      redirect_uri: 'http://localhost:3000/callback',
      code_verifier: window.localStorage.getItem('verifier')
    }

    let endpoint = new URL('https://accounts.spotify.com/api/token');

    endpoint.search = new URLSearchParams(newParams);

    fetch(endpoint.toString(), {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
      }
    }).then(data => data.json()).then(console.log)

此时,经过我的两次尝试,我都收到了错误:

{ error: "invalid_grant", error_description: "code_verifier was incorrect" }

我有什么明显做错的吗?该错误使我相信就 code_verifier 的实际生成而言我做错了什么,但我不知道这个问题可能是什么。

【问题讨论】:

  • 你解决了吗?在这里遇到完全相同的问题。我很确定这不是编码,但我不知道 Spotify 到底在做什么。
  • 很遗憾没有。我从这个项目中抽出一些时间,因为我觉得我已经用尽了我的选择。在不久的将来,我将尝试以全新的眼光再次审视它,如果我取得任何进展,我一定会更新此线程。
  • 好的。如果我找到任何东西,我会告诉你的。不知道出了什么问题,我猜文档太新了,可能在某个地方有点不准确。
  • 我也在 Spotify 开发者论坛上问过here
  • 太棒了。谢谢你。我认为这是我的问题的部分原因是因为here 在第一个回复中,有人声称已经用这个流程做了“概念证明”。

标签: javascript oauth-2.0 pkce


【解决方案1】:

Spotify 论坛上有人将我指向this 答案。不知道为什么,但是按照以下方式进行编码确实有效:

    async function sha256(plain) {
      const encoder = new TextEncoder()
      const data = encoder.encode(plain)
    
      return window.crypto.subtle.digest('SHA-256', data)
    }
    
    function base64urlencode(a){
      return btoa(String.fromCharCode.apply(null, new Uint8Array(a))
        .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')
    }
    
    const hashed = await sha256(verifyCode)
    const codeChallenge = base64urlencode(hashed)

【讨论】:

  • 有人可以确认这是否仍然有效吗?我似乎无法让它工作,并且 Spotify 的 api 错误消息不够详细,无法调试问题:|
【解决方案2】:

除了 OP 之外,以前的答案和 cmets 已经记录了所需的大部分信息,所以我只会添加对我有帮助的内容:

验证器本身大多被编码为 Base64-URL。

伪代码(我自己用 C# 编写代码):

verifier = Base64UrlEncode(GetRandomString(length: 50))
challenge = Base64UrlEncode(HashWithSha256(verifier))

【讨论】:

    猜你喜欢
    • 2020-12-30
    • 2020-12-08
    • 1970-01-01
    • 1970-01-01
    • 2021-08-03
    • 2021-03-12
    • 1970-01-01
    • 2021-03-18
    • 2020-12-04
    相关资源
    最近更新 更多