firebase-admin 8.6.1, firebase-tools 7.8.1Calling 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)
This happens after exchanging a client side ID token for a session cookie and then trying to later decode it.
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
});
});
});
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.
Most helpful comment
It appears you are passing a session cookie to
verifyIdToken. To verify a session cookie, you need to useverifySessionCookie.