Verifying firebase custom token to get token ID fails when using jsonwebtoken

11,105

Solution 1

It looks like you're calling verifyIdToken with a custom token. That's not going to work. verifyIdToken only accepts "ID tokens". To obtain an ID token from a custom token first call signInWithCustomToken(). Then call getToken() on the signed in user instance.

Solution 2

If you dont want to use signInWithCustomToken() this is the correct way to do it

const publicKey = new NodeRSA().importKey(serviceAccount.private_key, "pkcs8-private-pem").exportKey("pkcs8-public-pem")

jwt.verify(token, publicKey, {
        algorithms: ["RS256"]
    }, (err, decoded) => {
        if (err) {
            # send some error response
            res.status(400).json({
                status: 0,
                message: "Token is invalid!"
            })
        } else {
            # send some valid response
            res.status(200).json({
                status: 1,
                message: "Token is valid for uid " + decoded.uid
            })
        }
    })
Share:
11,105
Harry Lincoln
Author by

Harry Lincoln

Technology has always, and hilariously, served me pretty well… when in any doubt I have always found that the best way to deal with a problem is to know how to ask the right question and research the appropriate framework/solution. I am a mid/senior js developer with solid commercial experience using Angular1, looking to get into a frontend engineer role using Angular2 (as a preference because of personal project applications), but am of course willing and wanting to learn any. I also write frontend opinion-based pieces on Medium. My latest is all about my experiences with Angular2 and Google's database provider Firebase: https://medium.com/@harrylincoln/how-i-wanted-a-new-js-project-and-partially-learnt-angular2-820bd87ed686

Updated on June 14, 2022

Comments

  • Harry Lincoln
    Harry Lincoln about 2 years

    On the backend a custom token is generated via firebase's admin SDK thusly:

    router.use('/get-token', (req, res) => {
        var uid = "big-secret";
        admin.auth().createCustomToken(uid)
          .then(function(customToken) {
            res.json({
              instanceID: customToken
            });
          })
          .catch(function(error) {
            console.log("Error creating custom token:", error);
        });
    });
    

    The client frontend app then picks up the customToken and with it makes a request back to the backend to verify:

    const fbPrivateKey = serviceAccount.private_key;
    const key = new NodeRSA(fbPrivateKey).exportKey('pkcs8-public-pem');
    router.get('/verifyIdToken', cors(), (req, res) => {
      jwt.verify(req.headers.authorization.split('Bearer ')[1], key, { algorithms: ['RS256'] }, function(err, decoded) {
        console.log('err', err);
        console.log('decoded', decoded);
      });
    

    This always errors with the message: JsonWebTokenError: invalid signature

    Does this need signing? If anyone could explain this or has any pointers?

    UPDATE: When running req.headers.authorization.split('Bearer ')[1] through jwt.io is says that the signature is invalid, but then I enter my private key (key) and it validates.

    Am I getting the method calls incorrect or passing the wrong arguments into jwt.verify() ?