Dart/Flutter 中的 Spotify PKCE:"code_verifier was incorrect"
Spotify PKCE in Dart/Flutter: "code_verifier was incorrect"
将授权代码流与 Spotify-API 的 PKCE 结合使用我得到的错误是我的 code_verifier 不正确,据我所知这一定是编码问题。
{"error":"invalid_grant","error_description":"code_verifier was incorrect"}
这是我写的原始代码:
String getAuthUrl() {
code = getRandomString(128);
// saveToPrefs("verfifier_code", code);
var hash = sha256.convert(ascii.encode(code));
String code_challenge = base64Url.encode(hash.bytes);
return Uri.parse(
"https://accounts.spotify.com/authorize?response_type=code&client_id=${widget.client_id}&redirect_uri=http%3A%2F%2Flocalhost%2Fauth&scope=user-top-read&code_challenge=$code_challenge&code_challenge_method=S256")
.toString();
}
这就是我对 Spotify 授权指南 (https://developer.spotify.com/documentation/general/guides/authorization-guide/) 的理解。
找到这个 post () 后,我尝试将修复移植到 Dart 但失败了。据我了解,代码对 ascii 编码的 code_verifier 进行哈希处理,然后使用 btoa() 再次将其转换为 ascii。这个函数好像也做base64(但不是base64Url,也许这就是为什么某些部分必须手动替换的原因?)。
String getAuthUrl() {
// also tried static verifier_codes for debugging, so the getRandomString() function is working properly
code = getRandomString(128);
// saveToPrefs("verfifier_code", code);
var hash = sha256.convert(ascii.encode(code));
// this does not work with either base64 or base64Url
String code_challenge = base64.encode(hash.bytes).replaceAll(RegExp(r"/\+/g"), '-').replaceAll(RegExp(r"/\//g"), '_').replaceAll(RegExp(r"/=+$/"), '');
return Uri.parse(
"https://accounts.spotify.com/authorize?response_type=code&client_id=${widget.client_id}&redirect_uri=http%3A%2F%2Flocalhost%2Fauth&scope=user-top-read&code_challenge=$code_challenge&code_challenge_method=S256")
.toString();
}
我也尝试了不同的编码方式:
-使用String.codeUnits(但这是使用UTF-16)
- 为 sha256 函数以及带有 String.fromCharCodes() 的 base64(-Url) 函数获取字符串(应该使用 ASCII?)
- 在 ASCII 和 UTF-8 之间切换(在这种情况下应该没有什么区别,因为我的 verifier_code 仅由 ASCII 字符组成)
编辑:
为了提出我使用的请求:
var res = await http.post(endpoint, body: {"client_id":widget.client_id, "grant_type":"authorization_code", "code":value, "redirect_uri":"http://localhost/auth", "code_verifier":code});
经过更多研究后,我发现正在发生的重要事情是必须删除挑战末尾的“=”(base64Url 不应该那样做吗?)。无论如何,这是工作代码:
编辑代码:
String getAuthUrl() {
code = getRandomString(128);
var hash = sha256.convert(ascii.encode(code));
String code_challenge = base64Url.encode(hash.bytes).replaceAll("=", "").replaceAll("+", "-").replaceAll("/", "_");
return Uri.parse(
"https://accounts.spotify.com/authorize?response_type=code&client_id=${widget.client_id}&redirect_uri=http%3A%2F%2Flocalhost%2Fauth&scope=user-top-read&code_challenge=$code_challenge&code_challenge_method=S256")
.toString();
}
编辑:
另外“+”必须换成“-”,“/”换成“_”!
将授权代码流与 Spotify-API 的 PKCE 结合使用我得到的错误是我的 code_verifier 不正确,据我所知这一定是编码问题。
{"error":"invalid_grant","error_description":"code_verifier was incorrect"}
这是我写的原始代码:
String getAuthUrl() {
code = getRandomString(128);
// saveToPrefs("verfifier_code", code);
var hash = sha256.convert(ascii.encode(code));
String code_challenge = base64Url.encode(hash.bytes);
return Uri.parse(
"https://accounts.spotify.com/authorize?response_type=code&client_id=${widget.client_id}&redirect_uri=http%3A%2F%2Flocalhost%2Fauth&scope=user-top-read&code_challenge=$code_challenge&code_challenge_method=S256")
.toString();
}
这就是我对 Spotify 授权指南 (https://developer.spotify.com/documentation/general/guides/authorization-guide/) 的理解。
找到这个 post (
String getAuthUrl() {
// also tried static verifier_codes for debugging, so the getRandomString() function is working properly
code = getRandomString(128);
// saveToPrefs("verfifier_code", code);
var hash = sha256.convert(ascii.encode(code));
// this does not work with either base64 or base64Url
String code_challenge = base64.encode(hash.bytes).replaceAll(RegExp(r"/\+/g"), '-').replaceAll(RegExp(r"/\//g"), '_').replaceAll(RegExp(r"/=+$/"), '');
return Uri.parse(
"https://accounts.spotify.com/authorize?response_type=code&client_id=${widget.client_id}&redirect_uri=http%3A%2F%2Flocalhost%2Fauth&scope=user-top-read&code_challenge=$code_challenge&code_challenge_method=S256")
.toString();
}
我也尝试了不同的编码方式:
-使用String.codeUnits(但这是使用UTF-16)
- 为 sha256 函数以及带有 String.fromCharCodes() 的 base64(-Url) 函数获取字符串(应该使用 ASCII?)
- 在 ASCII 和 UTF-8 之间切换(在这种情况下应该没有什么区别,因为我的 verifier_code 仅由 ASCII 字符组成)
编辑:
为了提出我使用的请求:
var res = await http.post(endpoint, body: {"client_id":widget.client_id, "grant_type":"authorization_code", "code":value, "redirect_uri":"http://localhost/auth", "code_verifier":code});
经过更多研究后,我发现正在发生的重要事情是必须删除挑战末尾的“=”(base64Url 不应该那样做吗?)。无论如何,这是工作代码:
编辑代码:
String getAuthUrl() {
code = getRandomString(128);
var hash = sha256.convert(ascii.encode(code));
String code_challenge = base64Url.encode(hash.bytes).replaceAll("=", "").replaceAll("+", "-").replaceAll("/", "_");
return Uri.parse(
"https://accounts.spotify.com/authorize?response_type=code&client_id=${widget.client_id}&redirect_uri=http%3A%2F%2Flocalhost%2Fauth&scope=user-top-read&code_challenge=$code_challenge&code_challenge_method=S256")
.toString();
}
编辑:
另外“+”必须换成“-”,“/”换成“_”!