且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何使用存储在Firebase身份验证模拟器中的用户在功能模拟器中对Firebase云功能进行身份验证?

更新时间:2023-12-03 10:29:34

该仿真器仅用于本地测试,不用于生产,并且您不能使用仿真器发出的IdToken来访问Firebase Functions等其他服务,因为和文档说:

出于安全原因,身份验证模拟器会发布未签名的ID仅接受verifyIdToken和createSessionCookie的令牌在Cloud Functions中运行时Firebase Admin SDK的版本模拟器.

因此,这些令牌仅在仿真器环境中有效,并且如果您想将它们与Firebase Function一起使用,则只能在Functions仿真器中使用.有关如何在本地运行功能的信息,请本指南.

My firebase cloud function contains protected routes that can only be accessed when passed a valid IdToken in the request header. cloud functions API looks like this

functions/index.js


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

admin.initializeApp({
  credential: admin.credential.applicationDefault(),
  databaseURL: "DB_URL"
});

const express = require('express');
const app = express();


const authenticate = async (req, res, next) => {
  if (!req.headers.authorization || !req.headers.authorization.startsWith('Bearer ')) {
    res.status(403).send('Unauthorized');
    return;
  }
  const idToken = req.headers.authorization.split('Bearer ')[1];
  try {
    const decodedIdToken = await admin.auth().verifyIdToken(idToken);
    req.user = decodedIdToken;
    next();
    return;
  } catch(e) {
    res.status(403).send('Unauthorized');
    return;
  }
};

app.use(authenticate);


app.get('/protected', async (req, res) => {
    return res.send('OK');
});

exports.api = functions.https.onRequest(app);

Initially, I was using the Firebase Authentication to create new user and to get IdToken

Creating new user

curl 'https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=[API_KEY]' \
-H 'Content-Type: application/json' \
--data-binary '{"email":"[user@example.com]","password":"[PASSWORD]","returnSecureToken":true}'

Getting IdToken so I can pass it to the firebase cloud functions to access the protected routes

curl 'https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=[API_KEY]' \
-H 'Content-Type: application/json' \
--data-binary '{"email":"[user@example.com]","password":"[PASSWORD]","returnSecureToken":true}'

calling my protected cloud functions using this approach is working fine

curl --location --request GET 'http://localhost:5001/abc-production/us-central1/api/protected/' \
--header 'Authorization: Bearer SECRET_ID_TOKEN'

Now, Instead of using the Firebase Authentication, I'd like to use the Authentication Emulator to create new users and generate IdToken's.

I can create new users using the Auth emulator UI, but how do I generate the access token of those users? Are there any API endpoints that can return the IdToken of the locally saved user so that I can test my protected API without adding users in production?

Also, When I run the auth emulator, IdToken's generated using the production Firebase Authentication environment doesn't work.

"code": "auth/argument-error",
        "message": "Firebase ID token has invalid signature. See https://firebase.google.com/docs/auth/admin/verify-id-tokens for details on how to retrieve an ID token."

The emulator is intended only for local testing and not for production and you cannot use the IdToken issued by the emulator to access other services like Firebase Functions because and as the documentation says:

For security reasons, the Authentication emulator issues unsigned ID Tokens which are only accepted verifyIdToken and createSessionCookie of the Firebase Admin SDK when running inside the Cloud Functions emulator.

So, these token are only valid in the emulator environment and if you want to use them with Firebase Function, you can do that only with the Functions emulator. check this guide on how to run the functions locally.