无法通过具有客户端凭证流的 CloudFlare Worker OAuth 进入 Spotify API
Cannot OAuth into Spotify API through CloudFlare Worker with Client Credentials Flow
我正在尝试从 Spotify 获取访问令牌以进一步使用它来访问 Spotify API,而无需重定向 URL 到 Auth 确认页面。
我有一个 CloudFlare Worker 设置,其中包含此代码,但无论我尝试什么,它总是失败。
根据 Client Credential Flow 的文档,我应该向端点发出 POST 请求,如下所示:
const credentials = btoa(`${SPOTIFY_ID}:${SPOTIFY_SECRET}`);
const auth = await fetch("https://accounts.spotify.com/api/token", {
method: "POST",
headers: {
"Content-type": "application/x-www-form-urlencoded",
"Authorization": `Basic ${credentials}`,
},
body: JSON.stringify({
grant_type: "client_credentials",
}),
});
在此示例中,SPOTIFY_ID
和 SPOTIFY_SECRET
存储在 Worker 本身的环境变量中,并且是我的 Spotify APP 的有效凭据。 btoa()
方法根据 的格式请求将凭据转换为 Base64 并且输出正确(测试解码它成功)
我从 POST 请求得到的响应总是相同的:
{
"webSocket": null,
"url": "https://accounts.spotify.com/api/token",
"redirected": false,
"ok": false,
"headers": {},
"statusText": "Bad Request",
"status": 400,
"bodyUsed": false,
"body": {
"locked": false
}
}
还使用 curl 测试了 运行 请求,一切正常,它 returns 是一个有效的令牌。
我在 that this is supposed to be run server side because of the OAuth security convention, but the CloudFlare worker, even though runs on top of V8 上看到的也应该被视为服务器端,因为它在浏览器中没有 运行。
我想更好地理解为什么 CloudFlare Workers 环境似乎被视为客户端,如果我尝试使用 Spotify API Client for Node 编译时它不包含服务器端方法,也会发生这种情况,使它们 none 存在于已编译的 worker 中(可能是因为 Webpack 捆绑?)
另一个想法是 fetch()
方法默认是客户端的,所以一个可能的解决方案是使用另一个库向 Spotify 发出 POST 请求,但我不在 Workers 上不知道哪个可以用
我是不是漏掉了什么?这花了太多时间来解决,我没有任何提示。
我已经设法让它工作了,但我不知道如何以及为什么。
基本上通过阅读更多关于 OAuth 的问题,我想出了一个绕过的方法。
问题似乎是 body
参数可能与 fetch()
方法发生冲突。
正如 Kenton 提到的,我试图寻找更多错误信息,最终我用旧代码发现了这个:
{
"error": "unsupported_grant_type",
"error_description": "grant_type parameter is missing"
}
在我将 credentials
更改为完全解析为 const 而不是在 headers
对象的 Authorization
键下对其求值之前未打印此内容。
让它在 CloudFlare Workers 中工作的方法是 pass the body grant_type param as query string inside the URL
像这样:
const credentials = `Basic ${btoa(`${SPOTIFY_ID}:${SPOTIFY_SECRET}`)}`
const auth = await fetch("https://accounts.spotify.com/api/token?grant_type=client_credentials", {
method: "POST",
headers: {
"Content-type": "application/x-www-form-urlencoded",
Authorization: credentials,
},
});
我现在得到的是在 curl
中使用令牌的相同正确响应
{
"access_token": "randomstringthatrepresentsmytokenifinallysolvedthisshitthanksgodiwasgoinginsane",
"expires_in": 3600,
"token_type": "Bearer"
}
如果有人更清楚为什么这行得通而以前的行不通,我们鼓励您对此消息发表评论。
我正在尝试从 Spotify 获取访问令牌以进一步使用它来访问 Spotify API,而无需重定向 URL 到 Auth 确认页面。 我有一个 CloudFlare Worker 设置,其中包含此代码,但无论我尝试什么,它总是失败。 根据 Client Credential Flow 的文档,我应该向端点发出 POST 请求,如下所示:
const credentials = btoa(`${SPOTIFY_ID}:${SPOTIFY_SECRET}`);
const auth = await fetch("https://accounts.spotify.com/api/token", {
method: "POST",
headers: {
"Content-type": "application/x-www-form-urlencoded",
"Authorization": `Basic ${credentials}`,
},
body: JSON.stringify({
grant_type: "client_credentials",
}),
});
在此示例中,SPOTIFY_ID
和 SPOTIFY_SECRET
存储在 Worker 本身的环境变量中,并且是我的 Spotify APP 的有效凭据。 btoa()
方法根据
我从 POST 请求得到的响应总是相同的:
{
"webSocket": null,
"url": "https://accounts.spotify.com/api/token",
"redirected": false,
"ok": false,
"headers": {},
"statusText": "Bad Request",
"status": 400,
"bodyUsed": false,
"body": {
"locked": false
}
}
还使用 curl 测试了 运行 请求,一切正常,它 returns 是一个有效的令牌。
我在
我想更好地理解为什么 CloudFlare Workers 环境似乎被视为客户端,如果我尝试使用 Spotify API Client for Node 编译时它不包含服务器端方法,也会发生这种情况,使它们 none 存在于已编译的 worker 中(可能是因为 Webpack 捆绑?)
另一个想法是 fetch()
方法默认是客户端的,所以一个可能的解决方案是使用另一个库向 Spotify 发出 POST 请求,但我不在 Workers 上不知道哪个可以用
我是不是漏掉了什么?这花了太多时间来解决,我没有任何提示。
我已经设法让它工作了,但我不知道如何以及为什么。
基本上通过阅读更多关于 OAuth 的问题,我想出了一个绕过的方法。
问题似乎是 body
参数可能与 fetch()
方法发生冲突。
正如 Kenton 提到的,我试图寻找更多错误信息,最终我用旧代码发现了这个:
{
"error": "unsupported_grant_type",
"error_description": "grant_type parameter is missing"
}
在我将 credentials
更改为完全解析为 const 而不是在 headers
对象的 Authorization
键下对其求值之前未打印此内容。
让它在 CloudFlare Workers 中工作的方法是 pass the body grant_type param as query string inside the URL
像这样:
const credentials = `Basic ${btoa(`${SPOTIFY_ID}:${SPOTIFY_SECRET}`)}`
const auth = await fetch("https://accounts.spotify.com/api/token?grant_type=client_credentials", {
method: "POST",
headers: {
"Content-type": "application/x-www-form-urlencoded",
Authorization: credentials,
},
});
我现在得到的是在 curl
中使用令牌的相同正确响应{
"access_token": "randomstringthatrepresentsmytokenifinallysolvedthisshitthanksgodiwasgoinginsane",
"expires_in": 3600,
"token_type": "Bearer"
}
如果有人更清楚为什么这行得通而以前的行不通,我们鼓励您对此消息发表评论。