Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google OAuth2 JWT token verification exception

Tags:

I'm facing OAuth2 JWT token verification exception last hour (so no one can access my application):

java.security.SignatureException: Signature length not correct: got 256 but was expecting 128. I'm using google-http-client 1.20.0 and Java 1.7.0. Same configuration worked so far - any ideas?

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]
like image 491
user3686724 Avatar asked Jun 11 '15 12:06

user3686724


People also ask

How do I verify my Google JWT token?

After you receive the ID token by HTTPS POST, you must verify the integrity of the token. To verify that the token is valid, ensure that the following criteria are satisfied: The ID token is properly signed by Google. Use Google's public keys (available in JWK or PEM format) to verify the token's signature.

How do I authenticate a Google token?

To authenticate a user, a client application must send a JSON Web Token (JWT) in the authorization header of the HTTP request to your backend API. The Extensible Service Proxy (ESP) validates the token on behalf of your API, so you don't have to add any code in your API to process the authentication.


2 Answers

Same problem here, I added the source code of GoogleIdTokenVerifier to my project and changed the method:

 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;
  }

just handle the exception, the second certificate works fine.

Edit: you can subclass as Erik-z suggested if you want to make it more clean:

Edit 2: I can't make it work using the code below, I will stick to the ugly hack above.

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;
    }
}
like image 70
qtxo Avatar answered Oct 05 '22 00:10

qtxo


Don't think it's the final solution but a temporary work-around which definitely works is to change the audience of the verifier to the tokenId.

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

to

GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
                    .setAudience(Arrays.asList(tokenResponse.getIdToken())).build();
like image 21
Ittai Avatar answered Oct 05 '22 00:10

Ittai