在Java中正确比较code_verifier和code_challenge

时间:2019-08-20 11:53:05

标签: java oauth-2.0 passport.js pkce

我正在使用password-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安全的(无填充,无换行,+/的替代品),因此我使用的是网址解码器:

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

然后,我使用公共区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哈希处理,但是没有。

我在做什么错了?

1 个答案:

答案 0 :(得分: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();
    }