Skip to content

Compat + emulators isn't working well #2932

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
falk-stefan opened this issue Sep 8, 2021 · 10 comments
Closed

Compat + emulators isn't working well #2932

falk-stefan opened this issue Sep 8, 2021 · 10 comments

Comments

@falk-stefan
Copy link

falk-stefan commented Sep 8, 2021

It's been two completely wasted days now. I have not the slightest idea what could be wrong with my setup or what kind of information I am missing here but please somebody put me out of my misery here.

tl;dr: I follow a simple example where I want to create a new user using Google Sign-Up. The user gets created in the Auth service but not in the Firestore. I have no idea how my local firebaseConfig should look like and why this is not working.

Version info

Angular: 12

Firebase: 9.0.1

AngularFire: 7.0.3

Other (e.g. Ionic/Cordova, Node, browser, operating system):

Node: 16

How to reproduce these conditions

You can clone this repository and give it a try yourself.

I don't really know. All I did was run firebase init, and fire ap the base with:

$ npm run build --prefix functions && firebase emulators:start --inspect-functions & tsc --watch

All I am trying to to is save a new user to the Firestore:

  async googleSignIn() {
    this.logger.debug('User signs in with Google.')
    const provider = new auth.GoogleAuthProvider();
    const credentials = await this.afAuth.signInWithPopup(provider);
    return await this.updateUserData(credentials.user);
  }

  private async updateUserData(user: User | null) {

    if (!user) {
      throw "User cannot be null.";
    }

    const userRef: AngularFirestoreDocument<User> = this.afs.doc(`/users/${user.uid}`);
    const data: any = {
      uid: user.uid,
      email: user.email,
      displayName: user.displayName ? user.displayName : user.email,
      photoURL: user.photoURL
    }
    return userRef.set(data, {merge: true});
  }

Using

import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';

import {AppComponent} from './app.component';
import {AppRouting} from "./app.routing";
import {LoggerModule, NgxLoggerLevel} from "ngx-logger";
import {environment} from "../environments/environment";
import {HttpClientModule} from "@angular/common/http";
import {SharedModule} from "./modules/shared.module";
import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
import {AngularFireModule} from "@angular/fire/compat";
import {USE_EMULATOR as USE_AUTH_EMULATOR} from '@angular/fire/compat/auth';
import {AngularFirestore, USE_EMULATOR as USE_FIRESTORE_EMULATOR} from '@angular/fire/compat/firestore';
import {USE_EMULATOR as USE_FUNCTIONS_EMULATOR} from '@angular/fire/compat/functions';


const envFirebase = environment.firebase;

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    SharedModule,
    BrowserModule,
    BrowserAnimationsModule,
    HttpClientModule,
    AppRouting,

    // Logging
    LoggerModule.forRoot({
      serverLoggingUrl: '/',
      level: environment.production ? NgxLoggerLevel.OFF : NgxLoggerLevel.TRACE,
      serverLogLevel: NgxLoggerLevel.OFF
    }),
    // Firebase
    AngularFireModule.initializeApp(envFirebase.config),
  ],
  providers: [
    // Firebase
    {provide: USE_AUTH_EMULATOR, useValue: envFirebase.useEmulators ? ['http://localhost:9099'] : undefined},
    {provide: USE_FUNCTIONS_EMULATOR, useValue: envFirebase.useEmulators ? ['http://localhost:5001'] : undefined},
    {provide: USE_FIRESTORE_EMULATOR, useValue: envFirebase.useEmulators ? ['http://localhost:8080'] : undefined},
  ],
  bootstrap: [AppComponent]
})
export class AppModule {
  constructor(firestore: AngularFirestore) {
    firestore.firestore.settings({experimentalForceLongPolling: true})
  }
}

Debug output

After the user got created in the Authentication Service I am seeing this in my console.

** Errors in the JavaScript console **

FirebaseError: Missing or insufficient permissions.

Screenshot from 2021-09-08 18-36-00

Also:

export const environment = {
  production: false,
  firebase: {
    useEmulators: true,
    config: {
      apiKey: "*******",
      authDomain: ""*******-dev.firebaseapp.com",
      projectId: ""*******-dev",
      storageBucket: ""*******-dev.appspot.com",
      messagingSenderId: ""*******",
      appId: "1:"*******:web:"*******",
      measurementId: ""*******"
    },
  }
};

The interesting thing is that I see this in https://console.firebase.google.com/project/project/firestore/usage/last-24h/reads:

Screenshot from 2021-09-08 18-39-57

Even though I started using Emulators from the very beginning.

These are my Firestore settings:

Screenshot from 2021-09-08 18-40-46

which are the same as my local settings:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if true;
    }
  }
}
@google-oss-bot
Copy link

This issue does not seem to follow the issue template. Make sure you provide all the required information.

@jamesdaniels
Copy link
Member

Your Firestore and functions emulator tokens are in the wrong format. They’re inconsistent with auth, so you’re trying to hit prod with emulated credentials. Use [‘host’, port], see

{ provide: USE_AUTH_EMULATOR, useValue: environment.useEmulators ? ['http://localhost:9099'] : undefined },

‘Tis a silly API I know but it’s the one that shipped 😉

@falk-stefan
Copy link
Author

falk-stefan commented Sep 9, 2021

Please reopen this issue

@jamesdaniels I am not sure if this is correct. I started off with the ['host', port] format but that didn't work at all. I explicitly had to changed this to ['http://localhost:9099']. I think I saw a post somewhere (found it #2929 (comment)) that explains ['host', port] is not supported in the latest version anymore. I had to figure this out myself because it is nowhere documented. In other words the docs appear to be wrong about this.

Using your format will e.g. open the Auth pop-up at http://localhost/emulator/auth instead of http://localhost:9099/emulator/auth.

Also: How do you explain the "Permission denied" error I am receiving?

I am not sure if I understand:

"Your Firestore and functions emulator tokens are in the wrong format.."

What are emulator-tokens here?

Also:

"you’re trying to hit prod with emulated credentials"

I am not trying to hit production, I am trying to get Firestore working. As I stated, the Auth emulatore is working correctly with my configuration. What do you mean by "emulated" credentials?

@tja4472
Copy link

tja4472 commented Sep 9, 2021

Change

  providers: [
    // Firebase
    {provide: USE_AUTH_EMULATOR, useValue: envFirebase.useEmulators ? ['http://localhost:9099'] : undefined},
    {provide: USE_FUNCTIONS_EMULATOR, useValue: envFirebase.useEmulators ? ['http://localhost:5001'] : undefined},
    {provide: USE_FIRESTORE_EMULATOR, useValue: envFirebase.useEmulators ? ['http://localhost:8080'] : undefined},
  ],

to

  providers: [
    // Firebase
    {provide: USE_AUTH_EMULATOR, useValue: envFirebase.useEmulators ? ['http://localhost:9099'] : undefined},
    {provide: USE_FUNCTIONS_EMULATOR, useValue: envFirebase.useEmulators ? ['localhost', 5001] : undefined},
    {provide: USE_FIRESTORE_EMULATOR, useValue: envFirebase.useEmulators ? ['localhost', 8080] : undefined},
  ],

@falk-stefan
Copy link
Author

falk-stefan commented Sep 9, 2021

@tja4472 Copy pasted your suggestion but I still get the same. I'm not seeing any logs in http://localhost:4000/firestore/requests

Here are my rules from firestore.rules

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if true;
    }
  }
}

This is what's set in firebase.json

  "firestore": {
    "rules": "firestore.rules",
    "indexes": "firestore.indexes.json"
  },

Well.. the error message changed slightly but essentially I'm still getting "permission denied":

Screenshot from 2021-09-09 15-56-09

@falk-stefan
Copy link
Author

@tja4472 @jamesdaniels

I have now created a repository from scratch. There's a single button that you can use i.o. to try out the Google sign-in.

If you want to reproduce the issue I have just clone https://github.com/falk-stefan/angularfire-i2932

@jamesdaniels jamesdaniels reopened this Sep 9, 2021
@jamesdaniels
Copy link
Member

I'm able to reproduce, it turns out my sample still had a v9 release candidate... this seems like an issue with the JS SDK however, I'll investigate.

@jamesdaniels jamesdaniels changed the title Can't manage to work with the Firestore Emulator (actually nothings works) Compat + emulators isn't working well Sep 9, 2021
@jamesdaniels
Copy link
Member

Updating my firebase-tools fixed the issue, it does seem that Firebase v9 requires newer versions of the emulators. Guessing it has something to do with fetch vs xmlhttprequest. Downloading your repo now.

@jamesdaniels
Copy link
Member

confirmed fixed, no trouble with your repo if firebase-tools is updated.

@falk-stefan
Copy link
Author

@jamesdaniels Thanks a lot! 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants