Dockerfile
ARG VARIANT="14-buster"
FROM mcr.microsoft.com/vscode/devcontainers/typescript-node:0-${VARIANT}
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install --no-install-recommends openjdk-11-jre-headless
RUN echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] http://packages.cloud.google.com/apt cloud-sdk main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list && curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key --keyring /usr/share/keyrings/cloud.google.gpg add - && apt-get update -y && apt-get install google-cloud-sdk -y
RUN sudo -u node npm install -g @nestjs/[email protected] [email protected] [email protected]
If the 'application_default_credentials.json' is not present in the gcloud config path I get the error from below when I try to call any auth method even though the emulator is started, the FIREBASE_AUTH_EMULATOR_HOST env var is correctly set and the initializeApp is correctly called.
Based on my research this problem comes from the getApplicationDefault function inside the src/credential/credential-internal.ts file. I solved this by running gcloud auth application-default login (found on internet, don't know exactly what it does) which generated a valid application_default_credentials.json file
I don't completely understand the underlying mechanisms but I think this behaviour is not great for my use case which is probably very similar with a CI/CD pipeline use case. Also, there's nothing mentioned in the Firebase Auth emulator about this and I really like to be able to run all emulators without a real project but, doing this gcloud config makes me worried not to interact by mistake with the real gcloud project.
Error: Credential implementation provided to initializeApp() via the "credential" property failed to fetch a valid Google OAuth2 access token with the following error: "Error fetching access token: Error while making request: getaddrinfo ENOTFOUND metadata.google.internal metadata.google.internal:80. Error code: ENOTFOUND".
at FirebaseAppError.FirebaseError [as constructor] (C:\Users\Marian\Desktop\test\tp\node_modules\firebase-admin\lib\utils\error.js:43:28)
at FirebaseAppError.PrefixedFirebaseError [as constructor] (C:\Users\Marian\Desktop\test\tp\node_modules\firebase-admin\lib\utils\error.js:89:28)
at new FirebaseAppError (C:\Users\Marian\Desktop\test\tp\node_modules\firebase-admin\lib\utils\error.js:124:28)
at C:\Users\Marian\Desktop\test\tp\node_modules\firebase-admin\lib\firebase-app.js:124:23
at process._tickCallback (internal/process/next_tick.js:68:7)
I'm running a dev environment using the VSCode .devcontainer feature using the following files:
main.Dockerfile
ARG VARIANT="14-buster"
FROM mcr.microsoft.com/vscode/devcontainers/typescript-node:0-${VARIANT}
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install --no-install-recommends openjdk-11-jre-headless
RUN echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] http://packages.cloud.google.com/apt cloud-sdk main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list && curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key --keyring /usr/share/keyrings/cloud.google.gpg add - && apt-get update -y && apt-get install google-cloud-sdk -y
RUN sudo -u node npm install -g @nestjs/[email protected] [email protected] [email protected]
firebase_emulator.Dockerfile
ARG VARIANT="14-buster"
FROM mcr.microsoft.com/vscode/devcontainers/typescript-node:0-${VARIANT}
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install --no-install-recommends openjdk-11-jre-headless
RUN sudo -u node npm install -g [email protected]
COPY ./firebase.json .
COPY ./.firebaserc .
RUN firebase setup:emulators:database
RUN firebase setup:emulators:firestore
ENTRYPOINT [ "firebase", "emulators:start"]
docker-compose.yml
version: '3'
services:
main:
build:
context: .
dockerfile: main.Dockerfile
args:
VARIANT: 10
volumes:
- ..:/workspace
command: sleep infinity
environment:
FIRESTORE_EMULATOR_HOST: "firebase_emulator:8080"
FIREBASE_DATABASE_EMULATOR_HOST: "firebase_emulator:9000"
FIREBASE_AUTH_EMULATOR_HOST: "firebase_emulator:9099"
GCLOUD_PROJECT: "local"
links:
- firebase_emulator
firebase_emulator:
build:
context: .
dockerfile: firebase_emulator.Dockerfile
args:
VARIANT: 10
ports:
- "4000:4000"
- "5001:5001"
- "8080:8080"
- "9000:9000"
- "8085:8085"
- "4500:4500"
- "4400:4400"
- "9005:9005"
- "9099:9099"
devcontainer.json
{
"name": "Node.js & TypeScript & GCP & Firebase & Nest",
"dockerComposeFile":"docker-compose.yml",
"service": "main",
"workspaceFolder": "/workspace",
"settings": {
"terminal.integrated.shell.linux": "/bin/zsh",
"files.autoSave": "afterDelay",
"git.autofetch": true,
"workbench.iconTheme": "material-icon-theme"
},
"extensions": [
"dbaeumer.vscode-eslint",
"ms-vscode.vscode-typescript-tslint-plugin",
"eg2.vscode-npm-script",
"redhat.vscode-yaml",
"abhijoybasak.nestjs-files",
"nrwl.angular-console",
"esbenp.prettier-vscode",
"firsttris.vscode-jest-runner",
"github.vscode-pull-request-github",
"pkief.material-icon-theme",
"humao.rest-client"
],
"remoteEnv": {
"GITHUB_TOKEN": "${localEnv:GITHUB_TOKEN}",
"FIREBASE_TOKEN": "${localEnv:FIREBASE_TOKEN}"
},
"postCreateCommand": "npm install && npm install --only=dev",
"remoteUser": "node"
}
firebase.json
{
"emulators": {
"firestore": {
"port": 8080,
"host": "0.0.0.0"
},
"database": {
"port": 9000,
"host": "0.0.0.0"
},
"auth": {
"port": 9099,
"host": "0.0.0.0"
},
"ui": {
"enabled": true,
"port": 4000,
"host": "0.0.0.0"
}
}
}
.firebaserc
{
"projects": {
"default": "local"
}
}
The minimal code required is to call some auth function using the firebase-admin package. For example:
// The test script make sure the FIREBASE_AUTH_EMULATOR_HOST environment var is set
const process=require("process")
process.env.FIREBASE_AUTH_EMULATOR_HOST = "localhost:9099";
var admin = require('firebase-admin');
admin.initializeApp({
projectId: 'local'
})
admin.auth().createUser({});
Also running into this issue after trying to use the admin SDK as mentioned by @yuchenshi here: https://github.com/firebase/firebase-tools/issues/2749#issuecomment-718141997
One thing I did notice as well (likely separate ticket but maybe could be an easier workaround?). In @firebase/rules-unit-testing you can call initializeAdminApp and get what is suppose to be an admin app, but it's Auth doesn't have all the same methods as firebase-admin's Auth, namely createUser() which is what I specifically was trying to use to create users with specific uid's for testing
@imarian97 you mentioned: Firebase SDK version: v8.14.0. Note that the emulator support is only available on latest version (v9.3.0) of the SDK.
@imarian97 you mentioned:
Firebase SDK version: v8.14.0. Note that the emulator support is only available on latest version (v9.3.0) of the SDK.
Sorry! I have confused firebase-tools with firebase-admin-node. So, to clarify, I'm using the latest versions at the moment of writing and these versions are:
@IsaiahByDayah On your side comment on rules testing and initializeAdminApp: I think it's a completely different abstraction from the admin client, only meant for bypassing rules restrictions. Anyways, out of scope of this issue.
Haha, that would explain things wouldn't it 馃槄. My bad. I guess I just saw "admin" and made assumptions
@IsaiahByDayah ok there's a lot going on here so I have some questions.
Error: Credential implementation provided to initializeApp(), is this from code running within the Functions emulator? A script running elsewhere? Do you have to do anything besides 'emulators:start` to trigger this error?FIREBASE_TOKEN environment variable set, does the behavior change with/without that?@IsaiahByDayah ok there's a lot going on here so I have some questions.
- Where do you get this error
Error: Credential implementation provided to initializeApp(), is this from code running within the Functions emulator? A script running elsewhere? Do you have to do anything besides 'emulators:start` to trigger this error?- It seems like you have the
FIREBASE_TOKENenvironment variable set, does the behavior change with/without that?- Is there a simpler way I could reproduce this behavior? Are you able to get this to happen outside of docker / docker compose?
Hi, Considering the questions I suppose they are also addressed to me so:
Assuming you have the specified versions of node, npm and firebase-tools:
npm init -y in the foldernpm i firebase-admin in the folderfirebase.json file in the folder with the content from the initial comment.firebaserc file in the folder with the content from the initial commentindex.js file with the following content:var admin = require('firebase-admin');
admin.initializeApp({
projectId: 'local'
})
admin.auth().createUser({});
```
node index.jsSo I think this is working as intended, although I'd like to do some experiments myself to try. Setting the FIREBASE_AUTH_EMULATOR_HOST doesn't really change how firebase.initializeApp() works, since that initializes things for much more than Auth. And initializeApp() needs to be able to find a credential from somewhere. Some ways it can find a credential:
credential param with projectIdGOOGLE_APPLICATION_CREDENTIALS env var at a service account JSON file, thus authorizing as a service account.gcloud auth application-default login to put user credentials on your machine, thus authorizing as yourself.Now we try to hide this from you in a few cases:
initializeApp() inside Google Cloud, like in a Cloud Function or on App Engine or on Compute Engine, we can automatically discover the necessary credentials due to the trusted environment.initializeApp() inside the Cloud Functions Emulator, we simulate (1) by morphing your firebase login credentials into something the Admin SDK recognizes.So when running a script in a completely unauthorized docker container, I'd expect this error.
So I _think_ this is working as intended, although I'd like to do some experiments myself to try. Setting the
FIREBASE_AUTH_EMULATOR_HOSTdoesn't really change howfirebase.initializeApp()works, since that initializes things for much more than Auth. AndinitializeApp()needs to be able to find a credential from somewhere. Some ways it can find a credential:
- You could manually pass a
credentialparam withprojectId- You can point the
GOOGLE_APPLICATION_CREDENTIALSenv var at a service account JSON file, thus authorizing as a service account.- You can use
gcloud auth application-defaultlogin to put user credentials on your machine, thus authorizing as yourself.Now we try to hide this from you in a few cases:
- When you run
initializeApp()inside Google Cloud, like in a Cloud Function or on App Engine or on Compute Engine, we can automatically discover the necessary credentials due to the trusted environment.- When you run
initializeApp()inside the Cloud Functions Emulator, we simulate (1) by morphing yourfirebase logincredentials into something the Admin SDK recognizes.So when running a script in a completely unauthorized docker container, I'd expect this error.
I forgot to mention an important step but I suppose you already noticed it. The step was to remove or rename the application_default_credentials.json file which on Windows is located in %appdata%\gcloud
I understand that the initializeApp() needs the credentials but I don't really like to have to provide as a requirement a service account or some other form of credential to my CI/CD pipeline or, in my case, (at least in this stage of the development) to the local development environment, as long as I'm using only the emulators. For Firestore and RTDB emulators, based on my experience, the credentials are not required and I feel like the firebase-admin code can be updated (I have not spent enough time on it to understand how) to also not require the credentials for Auth Emulator.
I don't really have a problem with the credentials but I can't "fit the moment where you generate/obtain the credentials". For the CI/CD I know there are some ways to store a secret (the service account) and then retrieve it but that's extra work and configs considering that only emulators are used. But, for the local development scenario, it is even worse.
The ideal scenario for local development which I managed to achieve using the method described in the first comment is to have any developer of my team clone the repo and immediately start working on code (because I've containerized both the dev env and the Firebase Emulators so, everything is configured and starts automatically and the developer does not have to do anything). In this scenario, obtaining the credentials can be a bit annoying considering that including the service account in the repo is not a good practice and the developer might not even have access to a GCP/Firebase project (extremely possible for public projects)
I hope the scenarios and my issue are a bit clear now and I hope to find together (or, maybe, it already exists but I'm missing it) a good solution for completely local development and easy to use CI/CD.
Facing a similar issues here. Admin SDK cannot be used with the Auth emulator without providing valid application credentials.
The particular use case for me is a using the Admin SDK to seed/reset the emulators in a script. And while Admin SDK can successfully interact with the Firestore emulator without any application credentials, the Auth part of the Admin SDK requires application credentials with the Auth emulator.
I am also running into this issue. The documentation for the auth emulator recommends writing a script to create users, but I am not able to get admin-firebase to work this way unless I provide it with credentials to a real environment.
@dbanisimov @nVitius thanks for your feedback! According to @yuchenshi we may be able to fix this by lazily requiring credentials in firebase-admin-node when using Auth with the emulator.
This is fixed and released in version 9.4.0 of firebase-admin
Most helpful comment
@dbanisimov @nVitius thanks for your feedback! According to @yuchenshi we may be able to fix this by lazily requiring credentials in
firebase-admin-nodewhen using Auth with the emulator.