1

我正在使用 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 安全(无填充、无包装、替换+or /),所以我使用的是 URL 解码器:

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

然后我使用 commonsDigestUtils生成解码验证器的 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 散列,但事实并非如此。

我究竟做错了什么?

4

1 回答 1

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();
    }
于 2019-08-20T12:04:59.557 回答