Firebase-admin-node: Firebase ID token has incorrect "iss" (issuer) claim.

Created on 2 Dec 2019  路  2Comments  路  Source: firebase/firebase-admin-node

Describe your environment

  • Operating System version: macOS Catalina 10.15.1
  • Firebase SDK version:firebase-admin 8.6.1, firebase-tools 7.8.1
  • Firebase Product: auth, functions emulator
  • Node.js version: 13.0.1
  • NPM version: 6.13.1

Describe the problem

Calling admin.auth().verifyIdToken is giving an error:

Firebase ID token has incorrect "iss" (issuer) claim. Expected
"https://securetoken.google.com/"roboflow-platform" but got
"https://session.firebase.google.com/roboflow-platform". 
Make sure the ID token comes from the same Firebase project as 
the service account used to authenticate this SDK. 
See https://firebase.google.com/docs/auth/admin/verify-id-tokens 
for details on how to retrieve an ID token.

It looks like somewhere along the way the securetoken.google.com and session.firebase.google.com domains are getting added; they aren't present anywhere in my code.

I've tried downloading a new service account (both for the App Engine default service account and the firebase-adminsdk service accounts) but the project_id is the same for all of them.

The token I'm using was generated by the firebase web client with the defaults taken from the getting started guide and then exchanged via admin.auth().createSessionCookie as described in Manage Session Cookies.

I'm using "authDomain": "roboflow-platform.firebaseapp.com" in the initializeApp call on the frontend (but actually auth'd via localhost:5000)

Steps to reproduce:

This happens after exchanging a client side ID token for a session cookie and then trying to later decode it.

Relevant Code:

This is the middleware that's producing the error (slightly adapted from the Manage Session Cookies page).

const validateFirebaseIdToken = async (req, res, next) => {
    let idToken;
    if(req.cookies && req.cookies.session) {
        console.log('Found "__session" cookie');
        // Read the ID Token from cookie.
        idToken = req.cookies.session;
    } else {
        // No cookie
        res.status(403).send('Unauthorized');
        return;
    }

    try {
        const decodedIdToken = await admin.auth().verifyIdToken(idToken);
        console.log('ID Token correctly decoded', decodedIdToken);
        req.user = decodedIdToken;
        next();
        return;
    } catch (error) {
        console.error('Error while verifying Firebase ID token:', error); // <<-- produces the error above
        res.status(403).send('Unauthorized');
        return;
    }
};

The endpoint that created the token:

app.post('/session', function(req, res) {
    const expiresIn = 60 * 60 * 24 * 5 * 1000;
    admin.auth().createSessionCookie(req.body.token, {expiresIn}).then((sessionCookie) => {
        // Set cookie policy for session cookie.
        res.cookie('session', sessionCookie, {
            maxAge: expiresIn,
            httpOnly: true,
            secure: req.headers['x-forwarded-host'].indexOf('localhost') < 0
        });

        res.send('Ok');
    }, error => {
        res.status(401).send('UNAUTHORIZED REQUEST! ' + error);
    });
});

And the frontend code that exchanged to ID token:

user.getIdToken().then(function(token) {
    getCsrf(function(csrf) {
        $.post('/session', {
            csrf: csrf,
            token: token
        });
    });
});
auth

Most helpful comment

It appears you are passing a session cookie to verifyIdToken. To verify a session cookie, you need to use verifySessionCookie.

All 2 comments

It appears you are passing a session cookie to verifyIdToken. To verify a session cookie, you need to use verifySessionCookie.

Ahhhhh... that fixed it. Thank you so much for your help!

Would love to have had a more helpful error message -- not sure if there's a way to detect that failure case or not.

Was this page helpful?
0 / 5 - 0 ratings