Spotify Auth API返回400错误:code_verifier不正确的排查求助
解决Spotify PKCE授权中code_verifier不正确的问题
你的核心问题出在code_challenge的生成逻辑不符合PKCE规范:PKCE的S256方法要求对code_verifier字符串的ASCII字节做SHA-256哈希,而不是对生成code_verifier的原始随机字节做哈希,这直接导致服务器验证时哈希不匹配,返回错误。
错误原因分析
你的代码中,code_challenge是基于生成code_verifier的原始随机字节计算的:
_codeChallenge = base64UrlEncodeNoPadding((sha256.convert(codeVerifier).bytes));
但根据PKCE规范,正确逻辑应该是对编码后的code_verifier字符串的字节做哈希,而非原始随机字节。这就造成了你提交的code_challenge和服务器用code_verifier计算出的哈希完全不一致。
修正后的代码
1. 修正code_verifier和code_challenge生成逻辑
import 'dart:convert'; import 'dart:math'; import 'package:crypto/crypto.dart'; static void _createCodeVerifierAndChallenge() { final random = Random.secure(); // 生成32字节随机数据,转成URL安全的base64字符串(无填充)作为code_verifier final codeVerifierBytes = List<int>.generate(32, (_) => random.nextInt(256)); _codeVerifier = base64UrlEncodeNoPadding(codeVerifierBytes); // 关键修正:对code_verifier字符串的UTF-8字节做SHA-256哈希 final challengeBytes = utf8.encode(_codeVerifier); final challengeHash = sha256.convert(challengeBytes); _codeChallenge = base64UrlEncodeNoPadding(challengeHash.bytes); print('Code Verifier: $_codeVerifier'); print('Code Challenge: $_codeChallenge'); } static String base64UrlEncodeNoPadding(List<int> input) => base64Url.encode(input).replaceAll('=', '');
2. 额外检查点
- 确保
_codeVerifier和_codeChallenge在整个授权流程中未被重新生成:比如Flutter页面重建导致静态变量重置,或获取授权码后意外调用生成方法。建议将这两个值存入持久化存储(如SharedPreferences)避免状态丢失。 - 确认POST请求的
redirect_uri和GET授权请求中的完全一致,包括大小写、路径参数等,任何细微差异都会导致验证失败。 - 检查POST请求body的编码:Dart的http库传入Map作为body时,会自动处理
application/x-www-form-urlencoded编码,无需手动编码code_verifier。
内容的提问来源于stack exchange,提问作者tug89508
相关产品推荐
相关产品推荐

