【问题标题】:Correctly compare code_verifier with code_challenge in Java在 Java 中正确比较 code_verifier 和 code_challenge
【发布时间】:2019-08-20 21:17:57
【问题描述】:

我正在使用 passport-oauth2(passportjs.org 和 https://github.com/jaredhanson/passport-oauth2/blob/master/lib/strategy.js)在 nodejs 应用程序中进行 OAuth2+PKCE 集成。

它的身份验证所针对的后端是用 Java 编写的。

问题是我似乎无法解码->对 code_verifier 进行哈希处理以正确匹配来自 passport-oauth2 的 code_challenge。

我知道来自护照的 Base64 编码已生成为 URL 安全(无填充、无包装、替换 +/),所以我使用的是 URL 解码器:

Base64.getUrlDecoder().decode(...)

然后我使用 commons DigestUtils 生成解码验证器的 SHA256 并将其与挑战进行比较。所以整个事情看起来像这样:

    java.util.Base64.Decoder decoder = java.util.Base64.getUrlDecoder();
    String codeChallenge = // get the code challenge from my cache
    byte[] decodedCodeChallenge = decoder.decode(codeChallenge);
    byte[] decodedCodeVerifier = decoder.decode(codeVerifier);
    if (!Arrays.equals(sha256(decodedCodeVerifier), decodedCodeChallenge)) {
        return Response.status(400).entity(ERROR_INVALID_CHALLENGE_VERIFIER).build();
    }

示例:

此验证码:5CFCAiZC0g0OA-jmBmmjTBZiyPCQsnq_2q5k9fD-aAY 应该匹配这个代码挑战:Fw7s3XHRVb2m1nT7s646UrYiYLMJ54as0ZIU_injyqw 一旦两者都经过 Base64-url 解码并且验证器已经过 SHA256 散列,但它没有。

我做错了什么?

【问题讨论】:

    标签: java oauth-2.0 passport.js pkce


    【解决方案1】:

    5分钟后我就明白了。

    passport-oauth2中,验证码为Base64-url-encoded(random bytes)

    verifier = base64url(crypto.pseudoRandomBytes(32))
    

    见:https://github.com/jaredhanson/passport-oauth2/blob/master/lib/strategy.js#L236

    然后挑战是Base64-url-encoded(sha256(verifier)),扩展为Base64-url-encoded(sha256(Base64-url-encoded(random bytes)))

    challenge = base64url(crypto.createHash('sha256').update(verifier).digest());
    

    见:https://github.com/jaredhanson/passport-oauth2/blob/master/lib/strategy.js#L242

    所以要进行验证,我不需要解码任何东西。在它的编码状态是sha256-d。

    这最终奏效了:

        java.util.Base64.Encoder encoder = java.util.Base64.getUrlEncoder();
        String codeChallenge = // get code challenge from my cache;
        String encodedVerifier = new String(encoder.encode(sha256(codeVerifier))).split("=")[0]; // Remember to remove padding
        if (!encodedVerifier.equals(codeChallenge)) {
            return Response.status(400).entity(ERROR_INVALID_CHALLENGE_VERIFIER).build();
        }
    

    【讨论】:

    • 这里的加密是什么? crypto.pseudoRandomBytes(32) ?我试图生成一个代码验证器和一个 code_challenge 但我不知道什么是加密?
    • @Afsanefda 是nodejs.org/api/crypto.html 请记住:本场景中的客户端是运行passportjs 的NodeJS 客户端。服务器是 Java。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-15
    • 2021-01-28
    相关资源
    最近更新 更多