You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OAuth 2.0 PKCE授权报错:code_verifier无效(400错误)

排查Etsy OAuth 2.0的code_verifier无效问题

核心错误分析

代码存在两处致命逻辑错误,直接导致code_verifier is invalid报错:

  1. code_verifier与code_challenge定义混淆
    • OAuth 2.0 PKCE规范要求:code_verifier是原始随机字符串(经base64url编码),code_challenge是对该code_verifier做SHA256哈希后再base64url编码的结果。
    • 当前代码将base64url后的随机字符串误命名为$code_challenge,同时把哈希后的结果作为请求参数的code_challenge,还错误地将这个命名错误的变量存入session,在获取token时当作code_verifier传递,完全颠倒了两者的关系。
  2. SHA256哈希生成方式错误
    • PHP的hash('sha256', $str)默认返回十六进制字符串,而非原始二进制哈希值。直接对该十六进制字符串做base64编码,会导致哈希结果不符合Etsy的校验规则。必须传递第三个参数true以获取原始二进制哈希。

修正后的代码

生成授权URL的函数

function GetOauthUrl(){
    $_SESSION["etsy_state"] = getRadomString(128);
    
    // 生成32字节的密码学安全随机数据(符合PKCE规范的code_verifier长度要求)
    $randomBytes = random_bytes(32);
    // 对原始随机数据做base64url编码,得到合法的code_verifier
    $code_verifier = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($randomBytes));
    
    // 用code_verifier生成code_challenge:先做SHA256二进制哈希,再base64url编码
    $hashBinary = hash('sha256', $code_verifier, true);
    $code_challenge = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($hashBinary));
    
    // 构造授权URL
    $url = "https://www.etsy.com/oauth/connect?response_type=code&client_id={$_SESSION['etsy_clientId']}&redirect_uri={$_SESSION['etsy_url']}"
        ."&scope=listings_r%20listings_w%20listings_d&state={$_SESSION['etsy_state']}&code_challenge={$code_challenge}&code_challenge_method=S256";
    
    // 存储正确的code_verifier到session,用于后续获取token
    $_SESSION["etsy_code_verifier"] = $code_verifier;
    return $url;
}

获取Token的函数

function GetOauthToken(){
    $postfields = "grant_type=authorization_code&client_id=".$_SESSION["etsy_clientId"]
        ."&redirect Sitting单ur分享=$ and {am amodified的 Currentsubstituted with _ and = removed: ".$_SESSION['etsy_url']
        ."&code=".$_SESSION["etsy_authCode"]
        ."&code_verifier=".$_SESSION["etsy_code_verifier"]; // 使用存储的正确code_verifier

    $url = "/v3/public/oauth/token";

    return PostHttpRequest($url, array('Cache-Control: no-cache'), $postfields);
}

额外验证要点

  • 确保redirect_uri在授权URL和获取Token请求中完全一致,包括协议(http/https)、域名、路径,不能有任何差异。
  • 确认getRadomString函数生成的state是足够随机的字符串,用于防止CSRF攻击。
  • 使用random_bytes()替代rand()生成随机数据,rand()是伪随机且安全性较低,random_bytes()符合密码学安全要求。

内容的提问来源于stack exchange,提问作者MAtt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 22:05:40