谷歌 OAuth2 JWT 令牌验证异常

我在上一小时遇到了 OAuth2 JWT 令牌验证异常(因此没有人可以访问我的应用程序):

java.security.SignatureException:签名长度不正确:得到256,但期望128。我正在使用 和 .到目前为止,相同的配置有效 - 有什么想法吗?google-http-client 1.20.0Java 1.7.0

Stacktrace

java.security.SignatureException: Signature length not correct: got 256 but was expecting 128
    at sun.security.rsa.RSASignature.engineVerify(Unknown Source) ~[na:1.7.0_45]
    at java.security.Signature$Delegate.engineVerify(Unknown Source) ~[na:1.7.0_45]
    at java.security.Signature.verify(Unknown Source) ~[na:1.7.0_45]
    at com.google.api.client.util.SecurityUtils.verify(SecurityUtils.java:164) ~[google-http-client-1.20.0.jar:1.20.0]

答案 1

同样的问题,我将GoogleIdTokenVerifier的源代码添加到我的项目中并更改了方法:

 public boolean verify(GoogleIdToken googleIdToken) throws GeneralSecurityException, IOException {
    // check the payload
    if (!super.verify(googleIdToken)) {
      return false;
    }
    // verify signature
    for (PublicKey publicKey : publicKeys.getPublicKeys()) {
      try {
        if (googleIdToken.verifySignature(publicKey)) {
            return true;
          }
    } catch (Exception e) {
        System.err.println("Verify Token:" + e);
    }
    }
    return false;
  }

只需处理异常,第二个证书工作正常。

编辑:你可以像Erik-z建议的那样子类,如果你想让它更干净:

编辑2:我无法使用下面的代码使其工作,我将坚持上面的丑陋黑客。

package com.my.project.package;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.PublicKey;

import com.google.api.client.auth.openidconnect.IdTokenVerifier;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;

// Remember to remove this class later by making it deprecated
@Deprecated
public class GoogleIdTokenVerifier2 extends GoogleIdTokenVerifier {

    // Add constructors as needed
    public GoogleIdTokenVerifier2(HttpTransport transport, JsonFactory jsonFactory) {
        super(transport, jsonFactory);
    }

    @Override
    public boolean verify(GoogleIdToken googleIdToken) throws GeneralSecurityException, IOException {
        // check the payload
        if (!((IdTokenVerifier)this).verify(googleIdToken)) {
            return false;
        }
        // verify signature
        for (PublicKey publicKey : getPublicKeysManager().getPublicKeys()) {
            try {
                if (googleIdToken.verifySignature(publicKey)) {
                    return true;
                }
            } catch (Exception e) {
                System.err.println("Verify Token:" + e);
            }
        }
        return false;
    }
}

答案 2

不要认为这是最终的解决方案,但绝对有效的临时解决方法是将验证器的受众更改为tokenId。

GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory).setAudience(Arrays.asList(clientId)).build();

GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
                    .setAudience(Arrays.asList(tokenResponse.getIdToken())).build();