【问题标题】:OAuth2 and PKCE - Code verifier is invalidOAuth2 和 PKCE - 代码验证器无效
【发布时间】:2021-12-15 06:09:03
【问题描述】:

我正在制作一个 Java 应用程序,我正在尝试为需要 PKCE(代码交换证明密钥)的 API (Etsy.com) 实现 OAuth2 授权流程。我已经尝试了一段时间,但是在交换 OAuth 令牌的访问代码时,我一直遇到以下错误:

{"error":"invalid_grant","error_description":"code_verifier is invalid"}

下面是通过sha256编码验证器生成初始URL的方法:

@Override
public String getOAuth2AuthorizationUrl() {

    String sha256hex = null;
    try {
        if(_currentVerifier == null)
            _currentVerifier = PkceUtil.generateCodeVerifier();

        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] encodedhash = digest.digest(
                _currentVerifier.getBytes(StandardCharsets.UTF_8));
        sha256hex = new String(encodedhash);
    } catch (UnsupportedEncodingException | NoSuchAlgorithmException e) {
        e.printStackTrace();
        return null;
    }

    UnicodeEscaper basicEscaper = new PercentEscaper("-", false);
    System.out.println("sha256="+sha256hex);
    System.out.println("veri="+_currentVerifier);

    String oAuth2AuthorizationUrl = super.getOAuth2AuthorizationUrl();
    var authUrl = oAuth2AuthorizationUrl
            +"&state=asdf&code_challenge_method=S256&code_challenge='"
            + basicEscaper.escape(sha256hex)+"'";
    return authUrl;
}

然后我发送请求以交换令牌代码作为 application/x-www-form-urlencoded POST-request:

    UnicodeEscaper basicEscaper = new PercentEscaper("-", false);
 var params = "grant_type=authorization_code&client_id="
            +token.getOwner().clientId+"&redirect_uri="
            +basicEscaper.escape("https://localhost")
            +"&code="+accessCode+"&code_verifier="+basicEscaper.escape(_currentVerifier)+"";

我尝试了很多变体,还尝试将值包装在 '' 等中,但没有任何效果。我误解了这个过程吗?我最初发送一个 sha256 字符串,在请求 OAuth2 令牌时,我发送的是编码的值。 有什么想法吗?

更新: 我尝试使用 Google 库生成哈希,但仍然遇到同样的错误。

Hasher hasher = Hashing.sha256().newHasher();
    hasher.putString(CODE_VERIFIER, Charsets.UTF_8);
    HashCode sha256 = hasher.hash();

    System.out.println("veri="+AppUtils.encodeBase64(AppUtils.toHexString(sha256.asBytes())));

    String oAuth2AuthorizationUrl = super.getOAuth2AuthorizationUrl();

    var authUrl = oAuth2AuthorizationUrl
            +"&state=asdf&code_challenge_method=S256&code_challenge="+AppUtils.encodeBase64(AppUtils.toHexString(sha256.asBytes()));
    return authUrl;

code_challenge 参数的格式在示例中看起来也不同。

【问题讨论】:

    标签: java oauth pkce


    【解决方案1】:

    您的挑战生成不正确。验证者的哈希必须是base64 url encoded

    标准说

    code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
    

    所以这是错误的:

    sha256hex = new String(encodedhash);
    

    应该是:

    sha256hex = Base64.getUrlEncoder().withoutPadding().encodeToString(encodedhash);
    

    另外,不要在 URL 中的质询周围加上引号。

    旁注:没有必要逃避挑战和验证者,因为它们是以 url 安全的方式编码的

    【讨论】:

    • 谢谢,但还是不行。我在最初的帖子中添加了一些代码。
    • 添加一些示例输出(带有质询和验证器的 url 和表单正文)。
    • 第二次尝试时才注意到这一点:AppUtils.toHexString(...。这是错误的。不要这样做。 AppUtils 来自哪里?
    猜你喜欢
    • 2022-11-22
    • 2018-09-01
    • 2022-01-13
    • 1970-01-01
    • 2021-01-29
    • 2020-07-17
    • 2020-11-28
    • 2020-06-15
    • 1970-01-01
    相关资源
    最近更新 更多