This morning the following exception has started occuring on every API request to my Google Cloud Endpoint from my Android app:
com.google.api.server.spi.auth.GoogleIdTokenUtils verifyToken: verifyToken: Signature length not correct: got 256 but was expecting 128
The call still works perfectly from my javascript web clients. I have changed nothing on the server side code or client code.
Has anything changed with the service recently that might make this occur?
UPDATE: The first occurrence of this appears to have been at 11:17:07 UTC
UPDATE: Things that don't work include generating a new Client ID for android & updating to App Engine SDK 1.9.22
The causes
java.security.Signature.verify(byte[] signature)
throws an exception if a signature of the wrong length is passed (instead of returning false which is normally done when a signature does not match the key)For me the solution was to wrap the verify call (
try...catch
), and return false instead. You could also do an early check on the public key yourself, checking if the length of the signature matches the length of the public key modulus.If you use a library to check the signature, make sure you use the latest version.
Looking at the example code on http://android-developers.blogspot.nl/2013/01/verifying-back-end-calls-from-android.html, you would have to change this:
to
I unfortunately don't have an exact setup to test this.
For those using Google Cloud Endpoint, like the question states, I think there was very little you could do except wait until Google fixes it. Luckily it's fixed now. (Technically, you could argue changing the keys, as is done now, is a workaround, and the library Google provides needs to be fixed. But it works, so that's a good start)
Same problem here, as far as I can tell the public cert URL (now? I guess this wasn't the case before or the order changed) returns two keys:
https://www.googleapis.com/oauth2/v1/certs
inspecting those, the first has a 1024 bit key and the second a 2048 bit key. I believe my incoming tokens from android clients were signed by the second cert with the 2048 bit key, hence the "Signature length not correct: got 256 but was expecting 128".
Looking at the Google verifier source (GoogleTokenVerifier.java) it does appear to iterate multiple keys:
assuming the keys got parsed correctly (that code looks reasonable but haven't actually inspected the results).
As beestra pointed out the, this code expects false to be returned in case it could not be verified but instead it's throwing an exception. Ideally it should keep iterating after a failure and use the second public key to verify, which should work.
To fix this there appears to be two options:
I don't know how realistic 2. is, some super functionality is used and a lot of internal state is private, would have to duplicate all of it. Busy investigating...
UPDATE: Ok, looks to be fixed in my tests using production data, though haven't deployed it to production just yet. Here's the Scala
Just to be clear if it isn't obvious, using this method instead of Google's:
I'll try to write the Java equivalent later if anyone needs it.