Firebase-tools: [FR] Verifying emulated ID Tokens and creating session cookies only works in the Functions Emulator

Created on 30 Oct 2020  路  14Comments  路  Source: firebase/firebase-tools

[REQUIRED] Environment info

firebase-tools: 8.14.1

Platform: Windows 10

[REQUIRED] Test case

Currently emulating a scenario where a signed in user sends userToken from frontend and backend decoded this token and retrieves uid for fetching data from database.

const firebase = require('firebase/app');
require('firebase/auth');

const config = require('./config/firebaseConfig.json');

const firebaseConfig = {
  apiKey: config.apiKey,
  authDomain: config.authDomain,
  databaseURL: config.projectId,
  projectId: config.projectId,
  storageBucket: config.storageBucket,
  messagingSenderId: config.messagingSenderId,
  appId: config.appId,
  measurementId: config.measurementId
};

firebase.initializeApp(firebaseConfig);
firebase.auth().useEmulator("http://localhost:9099/");

const serviceAccountKey = require('./config/serviceAccountKey.json');

const admin = require('firebase-admin');

const databaseUrl = `http://localhost:9000/?ns=${config.projectId}`;
admin.initializeApp({
  credential: admin.credential.cert(serviceAccountKey),
  databaseURL: databaseUrl
});

const perform = async() => {
  const email = "[email protected]";
  const password = "password";
  await admin.auth().createUser({
    email: email,
    password: password
  });

  await firebase.auth().signInWithEmailAndPassword(email, password);
  const userToken = await firebase.auth().currentUser.getIdToken();

  // code fails here where admin is supposed to successfully verify id token
  await admin.auth().verifyIdToken(userToken);
};

perform();

[REQUIRED] Steps to reproduce

make sure that the following node packages are installed and firebase emulators for auth, firestore, and database are enabled:

 npm install -g firebase-tools
 npm install --save firebase
 npm install --save firebase-admin

[REQUIRED] Expected behavior

The userToken is decoded properly so that uid is extracted from the token for fetching data.

[REQUIRED] Actual behavior

It fails with Firebase ID token has no "kid" claim. The code is working normally except when using emulator.

WARNING: You are using the Auth Emulator, which is intended for local testing only.  Do not use with production credentials.
(node:24084) UnhandledPromiseRejectionWarning: Error: Firebase ID token has no "kid" claim. See https://firebase.google.com/docs/auth/admin/verify-id-tokens for details on how to retrieve an ID token.
    at FirebaseAuthError.FirebaseError [as constructor]
emulator-suite auth feature request

Most helpful comment

@favs-sama where are you running the admin code?

Right now verifyIdToken() for auth emulator tokens only works inside the Functions emulator. This is out of a concern for security, short-circuiting verifyIdToken() is obviously dangerous if it accidentally happens in production so right now we only allow it in the Functions emulator, which we can control fully.

I was planing to use the auth emulator to do tests without some weird workarounds required at the moment. I think that this behaviour (or at least some imitation of it) should be implemented for testing purposes. This also should have been mentioned at the documentation, would have saved me some time haha

All 14 comments

I'm running into this as well. I can't verify idTokens created by the emulator.

@favs-sama where are you running the admin code?

Right now verifyIdToken() for auth emulator tokens only works inside the Functions emulator. This is out of a concern for security, short-circuiting verifyIdToken() is obviously dangerous if it accidentally happens in production so right now we only allow it in the Functions emulator, which we can control fully.

@samtstern originally i'm running the admin code verifyIdToken() in a backend prehandler function for handling user authorization; so, no i'm not running this inside a firebase function. although is there any other way to approach this kind of testing if currently verifyIdToken() for auth emulator is only accessible via functions emulator?

@favs-sama yeah right now the only way to test this is inside the Functions emulator. We do want to change this eventually but it requires us to build in a more secure version of verifyIdToken() that would be less dangerous to your server in the event of a configuration mistake!

So for now I'll consider this a feature request.

I've created b/172262218 to track this feature request internally

Also running into this. Will be watching this issue.

I changed the name of this issue to more accurately reflect the feature request and include the use case from #2770

I'd need to verify/decode the token with the emulator as well.

@favs-sama where are you running the admin code?

Right now verifyIdToken() for auth emulator tokens only works inside the Functions emulator. This is out of a concern for security, short-circuiting verifyIdToken() is obviously dangerous if it accidentally happens in production so right now we only allow it in the Functions emulator, which we can control fully.

I was planing to use the auth emulator to do tests without some weird workarounds required at the moment. I think that this behaviour (or at least some imitation of it) should be implemented for testing purposes. This also should have been mentioned at the documentation, would have saved me some time haha

Does anyone have a workaround for this?

@samtstern just voicing my support for this - many, many engineers do not use https.callable and instead opt for express setups, myself included. Not being able to support this means that we have a lack of ability to test our client-server interaction through integration tests.

From an engineering perspective, shouldn't this be as easy as disabling the 'kid' claim check when a certain envvar is set to true (IE, an envvar that is only set when firebase is running emulator mode)? I don't particularly understand why this would be hard to facilitate.

@mjgerace we know how to do this, but we're being extra careful about security. If your production server ever got into a situation where it thought it should disable/skip ID token verification then you'd have a big problem!

In order to have _something_ in time for the launch of the Auth Emulator we compromised on a simple solution in the Node.js Admin SDK that is only enabled inside the Functions emulator. We are actively working on a longer-term solution that we're happier with and when we finish it we will bring it to all of our Admin SDKs (Node, Java, Go, Python, etc) so that you can develop on your own server.

@samtstern this makes total sense - is there any timeline for this work? In the meantime, would it be bad for our team to set an env var (FIREBASE_EMULATOR=1 yarn jest {test_file}) and otherwise workaround the issue in my actual auth middleware?

So long as I can modify the verifyIdToken() function, I could manually implement my suggested fix while I work on testing. Our app isn't in production and this would allow us to write tests without doing anything overly risky.

@mjgerace we never offer timelines but this is something we're actively working on, it's not on the backlog. If you want to work around this issue on your own server and you're confident you know how, go for it!

Was this page helpful?
0 / 5 - 0 ratings