2
votes

I'm using firebase for Android and IOS application. The Application has dedicated backend and verifies the Token issued by firebase after phone/email auth using verifyIdToken method. I'm verifying the token for new user registration. The concept is working fine for android application. When new user Authenticates, Registration API going to be called with Token issued by Firebase and I'm verifying that token using Service Account. However, For ios it fails with the exception that kid header is invalid. Here is the exception trace.

A key with ID "3494b1e786cdad092e423766bbe37f54ed87b22d" could not be found. 
{"exception":"[object] (Firebase\\Auth\\Token\\Exception\\UnknownKey(code: 0): 
A key with ID \"3494b1e786cdad092e423766bbe37f54ed87b22d\" could not be found.
at /home/fgx3uhiothty/public_html/vendor/kreait/firebase-tokens/src/Verifier.php:132)

In Firebase Auth Documentation, there is clearly stated that

kid Key ID Must correspond to one of the public keys listed at https://www.googleapis.com/robot/v1/metadata/x509/[email protected]

When I checked key 3494b1e786cdad092e423766bbe37f54ed87b22d with the google's public key after decoding token, I didn't find the kid matching. However, the token from ios device is issued by firebase itself after successful auth. So how is it possible having different kid header in ios token?

I'm using kreait/firebase-tokens-php library for accessing service account API from backend.

2
Thank you for writing this up and sharing it here - the issue was reported to me just a few times in the past couple of weeks, but often enough to reduce the likeability of some kind of misconfiguration. As I don't have the means to test/reproduce this myself, perhaps @frank-van-puffelen has some insight or ideas on the topic? My assumption so far was that the public keys got rotated after the issuance of the ID token, but I thought this to be really, really rare.jeromegamez
Oh God, You got it, The public keys are wrong, please not the kid header of the android token is correct. it happens to me with ios. This kind of bug affects the deployed system, I loose around 2k users. When I checked backend dashboard there is only 6.7k registered user and on firebase auth, the count is 8.4k. means so many users authenticated but can't be able to complete registration because of token verification error.Kiran Maniya
solved, Firebase Docs is not correct. LOLKiran Maniya
@Kiran Maniya. How did you solve? How can be changed the firebase docs? You mean, google public key url is incorrect? It has to be like this? https://www.googleapis.com/service_accounts/v1/metadata/x509/my_firebase_service_accountdevcrazy
@devcrazy Detailed answer below, still won't get solved, feel free to reach me.Kiran Maniya

2 Answers

1
votes

I figured out the issue, The behavior in ios devices are not identical to android because of firebase implementation. in ios, firebase redirects the user to the safari browser for email login and then returns flow to the app and it's not exactly same as android behavior.

I just worked around and decoded the firebase token. aud,iss and 'kid' header was not matching but was looking like a google's auth token issued from web hence I looked into Web Sign-in Backend Auth Docs from google and found a clue. I found a kid header of ios firebase token here in JWK and PEM. Well, i have to use the Google API Client Library and verified the token successfully.

In this case, for IOS device, the method verifyIdToken() of Firebase Admin SDK given in Firebase Admin SDK Official Docs won't be worked at all. I think Firebase should update their docs. after several attempts of reaching them out could not solve the problem, instead, they just pushed the tooltip like given below,

Tooltip from firebase Docs

I suggest, for ios Gmail Auth use the method given in Web Backend Auth instead of using verifyIdToken() of Firebase Admin SDK.

0
votes

I bet you are using a Google idToken, not a firebase idToken. How did you get your idToken? You can get idToken via this api: https://firebase.google.com/docs/reference/js/firebase.User#getidtoken

Signin Callback function maybe like following.

var signInCb = function(authResult) {
    var uid = authResult.user.uid;
    authResult.user.getIdToken()
        .then( idToken => {
            // You can do some things with idToken here
                ....
        })
}