firebase-admin-node icon indicating copy to clipboard operation
firebase-admin-node copied to clipboard

With preferRest: true option set, I am unable to connect to auth emulator

Open sushantdhiman opened this issue 2 years ago • 11 comments

Describe your environment

  • Operating System version: Arch Linux
  • Firebase SDK version: 11.4.0
  • Firebase Product: auth, firestore, storage
  • Node.js version: 18.x
  • NPM version: 8.19.1

Additional related dependencies

@google-cloud/[email protected]
@google-cloud/[email protected]
[email protected]

Describe the problem

With preferRest: true option set, I am unable to connect to auth emulator

Steps to reproduce:

Here is my firebase initialization code

import { initializeApp, applicationDefault } from 'firebase-admin/app';
import { getAuth } from 'firebase-admin/auth';
import { initializeFirestore } from 'firebase-admin/firestore';

export const app = initializeApp({                                                                                                
  credential: applicationDefault(),
  projectId: process.env.GCLOUD_PROJECT,
});

export const auth = getAuth(app);
---export const firestore = initializeFirestore(app);
+++export const firestore = initializeFirestore(app, { preferRest: true });

When I run my application with preferRest: true, I get this error. It seems like emulators are not detected with this option.

Error: Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information.
  at GoogleAuth.getApplicationDefaultAsync (/home/node/app/node_modules/google-auth-library/build/src/auth/googleauth.js:209:19)
  at GoogleAuth.getClient (/home/node/app/node_modules/google-auth-library/build/src/auth/googleauth.js:635:17)
  at GrpcClient.createStub (/home/node/app/node_modules/google-gax/src/fallback.ts:280:27)
Caused by: Error: 
  at L0.getAll (/home/node/app/lib/server.js:113:509361)
  at ta.get (/home/node/app/lib/server.js:113:32416)
  at Function.findByIdentifier (/home/node/app/src/database/user.ts:115:44)\n

Application works correctly without preferRest option.

sushantdhiman avatar Dec 16 '22 11:12 sushantdhiman

Hi @sushantdhiman, preferRest option is in firestore so it is a bit strange that you are experiencing issues with the auth API. You might have already done this, but just to confirm did you set the environment variables for Firestore and Auth emulator?

export FIREBASE_AUTH_EMULATOR_HOST="localhost:9099"
export FIRESTORE_EMULATOR_HOST="localhost:8080"

lahirumaramba avatar Dec 16 '22 17:12 lahirumaramba

I am also unable to reproduce this.

lahirumaramba avatar Dec 16 '22 18:12 lahirumaramba

I am experiencing the same.

From what I can tell, the function refreshTokenNoCache is using the constant below:

 const url = OAuth2Client.GOOGLE_OAUTH2_TOKEN_URL_

By logging the response error, I can see the URL is set to 'https://oauth2.googleapis.com/token'.

When the error occurs in generateServiceStub, the callback function does not exist, which swallows this error and instead reports that callback is undefined. So, to see the actual error, I needed a console.log when catching the error.

NB: I upgraded an existing project that worked OK; the variables above are set correctly. Hope it helps!

Gbuomprisco avatar Dec 18 '22 10:12 Gbuomprisco

did you set the environment variables for Firestore and Auth emulator?

I can confirm those environment variables are set.

Applications works correctly without preferRest: true, I am also facing this exact issue in another project.

sushantdhiman avatar Dec 19 '22 08:12 sushantdhiman

I have this issue too. When you enable preferRest, it seems like the auth emulator tries to setup credentials for the google-gax fallback?

It has the correct address set in the env passed into createStub and customServicePath is true, but this.auth.getClient() errors out.

https://github.com/googleapis/gax-nodejs/blob/main/src/fallback.ts#L280

ganey avatar Dec 19 '22 17:12 ganey

Hey everyone, thank you for your patience on this. We have identified the root cause and the team is currently working on a fix.

lahirumaramba avatar Jan 12 '23 16:01 lahirumaramba

@lahirumaramba Can you suggest some workaround while https://github.com/googleapis/gax-nodejs/issues/1409 is open? Perhaps we can mock/stub some methods so it works for tests?

sushantdhiman avatar Mar 22 '23 04:03 sushantdhiman

Also running into this.

maccman avatar Mar 30 '23 17:03 maccman

We have some momentum on a fix, but in the meantime there are two possible workarounds.

First, you could disable preferRest when using the emulator.

    const db = initializeFirestore(app, {
        preferRest: !process.env.FIRESTORE_EMULATOR_HOST
    });

Second, you can create this auth object for use with the emulator.

import { initializeApp, applicationDefault } from 'firebase-admin/app';
import { initializeFirestore } from 'firebase-admin/firestore';

export const app = initializeApp({
    credential: applicationDefault(),
    projectId: process.env.GCLOUD_PROJECT,
});

// Workaround pt 1 - add this createEmulatorAuth function
function createEmulatorAuth() {
    return {
        async getClient() {
            return {
                async getRequestHeaders() {
                    return {Authorization: 'Bearer owner'};
                }
            };
        },
    };
}

async function main() {
    const db = initializeFirestore(app, {
        preferRest: true
    });

    // Workaround pt 2 - Pass emulator auth here
    if (process.env.FIRESTORE_EMULATOR_HOST) {
        db.settings({
            auth: createEmulatorAuth()
        });
    }

    await db.collection("foo").add({time: Date.now()})
    const result = await db.collection("foo").get();

    console.log(result.size);
}
main();

MarkDuckworth avatar Apr 07 '23 18:04 MarkDuckworth

I don't seem to have any trouble connecting to auth emulator with preferRest. My config:

config/firebase.ts

import { initializeApp } from 'firebase-admin/app';
import { getAuth } from 'firebase-admin/auth';
import { getFirestore } from 'firebase-admin/firestore';
import { getStorage } from 'firebase-admin/storage';

const app = initializeApp();

const auth = getAuth(app);

const db = getFirestore(app);

db.settings({
  ignoreUndefinedProperties: true,
  preferRest: true,
});

const storage = getStorage(app);

export { auth, db, storage };

johnnyoshika avatar Jul 06 '23 18:07 johnnyoshika

I stand to be corrected. Although my app runs fine with auth emulator when preferRest is true, unit tests on Linux and macOS time out and fail. Interestingly this wasn't a problem on Windows, but this fixed Linux and macOS for me:

db.settings({
  ignoreUndefinedProperties: true,
  preferRest: !process.env.JEST_WORKER_ID,
});

johnnyoshika avatar Jul 07 '23 05:07 johnnyoshika