Ben*_*ham 4 javascript oauth-2.0 pkce
我很高兴听到我现在可以通过 PKCE 使用 Spotify Web API,而无需使用后端应用程序。不幸的是,我似乎有某种误解并且无法让它发挥作用。
一路上我可能犯了一些小错误,但我做了一次却无济于事,我把石板擦干净并再次尝试,但仍然没有运气。由此我推测我一定是误解了文档。
我将解释我在做什么,希望这里有人能指出我遗漏或做错的事情。我假设我有一个基本的概念误解。
我首先使用名为 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();
Run Code Online (Sandbox Code Playgroud)
从这里,我使用正确的 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)
Run Code Online (Sandbox Code Playgroud)
此时,经过两次尝试后,我收到了错误:
{ error: "invalid_grant", error_description: "code_verifier was incorrect" }
Run Code Online (Sandbox Code Playgroud)
我有什么明显做错的事情吗?这个错误让我相信就 code_verifier 的实际生成而言我做错了什么,但我不知道这个问题可能是什么。
Spotify 论坛上有人向我指出了这个答案。不知道到底为什么,但按以下方式进行编码确实有效:
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)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2191 次 |
| 最近记录: |