"Missing or insufficient permissions." error using emulators

2,512 views
Skip to first unread message

Roger Hopkins

unread,
Jun 21, 2021, 5:17:30 AM6/21/21
to Firebase Google Group
I haven't used the emulators in several months so I'm not sure if something changed or if there's something I'm missing.

I started the emulators and created a user in authentication.  After successfully signing in with email and password my app reads from a Firestore users collection.

However when it attempts to get a document I get the "Missing or insufficient permissions." error.

My security rules are pretty open and are the same as what I'm using in the real Firebase database.

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

I've even tried allow read, write: if true with the same result.

At this point I'm unable to test my app using the emulators which is especially a pain with functions since I have to deploy them in order to test.

Would appreciate any help.

Sam Stern

unread,
Jun 21, 2021, 5:29:46 AM6/21/21
to Firebase Google Group
Hi Roger,

If you're getting permissions errors with "allow read, write: if true" rules it sounds like your app is not actually connecting to the Emulators, it's probably talking to production where the rules are stronger.

Can you try to reduce this to a minimal example that we can reproduce?

Sam

--
You received this message because you are subscribed to the Google Groups "Firebase Google Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/68e6b4b5-fe74-45df-a523-6ab6939c83b6n%40googlegroups.com.

Roger Hopkins

unread,
Jun 26, 2021, 11:34:41 AM6/26/21
to Firebase Google Group
Hi Sam,

Finally had time to work on this and I've confirmed that the functions are using the emulator but Firestore is using the Firebase server.

First I set my rules to be read, write if true on both the emulator and the server.

I created a simple app with a button to read from a "users" collection.  When I used a document ID from the firestore emulator the get() didn't return the document.  When I used a document ID from a test Firebase project on the server it returned the document.

When I changed the rules on the server database to read, write: if request.auth.uid != null, I got the missing permissions error.

I also created a simple cloud function triggered when a document is created in the users collection which console logs the new document data.  When I created a new user document in the emulator UI, it triggered the function.

Here's my Firebase setup to use the emulators:
// Use emulators
if (window.location.hostname === 'localhost') {
firebaseStore.useEmulator("localhost", 8080)
firebaseFunctions.useEmulator("localhost", 5001)
firebaseAuth.useEmulator('http://localhost:9099')
}

Here's the output from the emulators:start:
i  hosting: Serving hosting files from: dist/spa
✔  hosting: Local server: http://localhost:5000
i  ui: Emulator UI logging to ui-debug.log
i  functions: Watching "/Volumes/Seagate/SoftwareDevelopment/App_Development/Playground/quasar-sandbox/functions" for Cloud Functions...
✔  functions[us-central1-newUser]: firestore function initialized.

┌─────────────────────────────────────────────────────────────┐
│ ✔  All emulators ready! It is now safe to connect your app. │
│ i  View Emulator UI at http://localhost:4000                │
└─────────────────────────────────────────────────────────────┘

┌────────────────┬────────────────┬─────────────────────────────────┐
│ Emulator       │ Host:Port      │ View in Emulator UI             │
├────────────────┼────────────────┼─────────────────────────────────┤
│ Authentication │ localhost:9099 │ http://localhost:4000/auth      │
├────────────────┼────────────────┼─────────────────────────────────┤
│ Functions      │ localhost:5001 │ http://localhost:4000/functions
├────────────────┼────────────────┼─────────────────────────────────┤
│ Firestore      │ localhost:8080 │ http://localhost:4000/firestore
├────────────────┼────────────────┼─────────────────────────────────┤
│ Hosting        │ localhost:5000 │ n/a                             │
├────────────────┼────────────────┼─────────────────────────────────┤
│ Storage        │ localhost:9199 │ http://localhost:4000/storage   │
└────────────────┴────────────────┴─────────────────────────────────┘
  Emulator Hub running at localhost:4400
  Other reserved ports: 4500

Here's the functions emulator log show the function triggered when I created a new user document:
16:22:14function[us-central1-newUser] Beginning execution of "us-central1-newUser"
16:22:14function[us-central1-newUser] new User RCwPn5fiOTLyPvipMcvb { golferID: '123' }
16:22:14function[us-central1-newUser] Finished "us-central1-newUser" in ~1s

Hope you can help me figure it out.

Thanks

Sam Stern

unread,
Jun 28, 2021, 9:44:19 AM6/28/21
to fireba...@googlegroups.com
Hi Roger,

Thanks for the details. So the implication here is that "firebaseStore.useEmulator("localhost", 8080)" is not working, so let's dig into that:
  • Where do you initialize the "firebaseStore" variable?
  • Do you change any other settings on "firebaseStore"? At any point?
  • Are you sure you're using the same "firebaseStore" variable to access your data?
- Sam

Roger Hopkins

unread,
Jun 28, 2021, 9:59:33 AM6/28/21
to fireba...@googlegroups.com

Hi Sam,

 

I’m using Quasar for Vuejs which imports the Firebase settings from a boot file.  I then import the Firebase objects into my Vuejs components and don’t modify it anywhere else.

 

Here’s the entire boot file followed by snippets from the JavaScript code .  As you can see I’m using environment variables for the config settings.

import firebase from 'firebase/app'

 

import 'firebase/auth'

import 'firebase/firestore'

import 'firebase/functions'

import 'firebase/storage'

 

// FIREBASE CONFIG

const firebaseConfig = {

  apiKey: process.env.firebaseConfig.apiKey,

  authDomain: process.env.firebaseConfig.authDomain,

  databaseURL: process.env.firebaseConfig.databaseURL,

  projectId: process.env.firebaseConfig.projectId,

  storageBucket: process.env.firebaseConfig.storageBucket,

  messagingSenderId: process.env.firebaseConfig.messagingSenderId,

  appId: process.env.firebaseConfig.appId,

  measurementId: process.env.firebaseConfig.measurementId

}

// Initialize Firebase Performance Monitoring.

// firebase.performance() TO-DO: Figure out how to include performance monitoring

 

const firebaseApp = firebase.initializeApp(firebaseConfig)

const firebaseAuth = firebaseApp.auth()

const firebaseFunctions = firebaseApp.functions()

const firebaseStore = firebaseApp.firestore()

const Timestamp = firebase.firestore.Timestamp

const Fieldvalue = firebase.firestore.Fieldvalue

const storage = firebase.storage()

 

// Use emulators

if (window.location.hostname === 'localhost') {

 

  firebaseStore.useEmulator("localhost", 8080)

  firebaseFunctions.useEmulator("localhost", 5001)

  firebaseAuth.useEmulator('http://localhost:9099')

}

 

// *** Use Firebase server

firebaseStore.settings({

  // ssl: false,

  ignoreUndefinedProperties: true

})

 

firebase.firestore().enablePersistence()

  .catch(function (error) {

    if (error.code === 'failed-precondition') {

      console.log('persistence failed-precondition')

    } else if (error.code === 'unimplemented') {

      console.log('persistence unimplemented')

    }

  })

 

export {

  firebaseAuth,

  firebaseFunctions,

  firebaseStore,

  Timestamp,

  Fieldvalue,

  storage

}

 

 

import { firebaseStore } from 'boot/firebase'

 

export default {

  name: 'PageTest',

  data () {

    return {

 

    }

  },

  components: {

 

  },

  methods: {

    async getUser () {

      try {

        const userID = 'MFMBgLxkVZN8YXuHNs2Dx2LSs3y2'

        const docRef = firebaseStore.collection("users").doc(userID);

 

        docRef.get().then((doc) => {

            if (doc.exists) {

                console.log("Document data:", doc.data());

            } else {

                console.log("No such document!");

            }

        }).catch((error) => {

            console.log("Error getting document:", error);

        });

        console.log(doc)

      } catch (error) {

        alert('error', `Error getting user info, error: ${error}`)

        this.usersLoaded = true

      }

    },

 

  }

 

}

 

Roger Hopkins

Sam Stern

unread,
Jun 30, 2021, 9:02:20 AM6/30/21
to fireba...@googlegroups.com
Hi Roger,

That's strange and I am having trouble seeing where this can go wrong. Mind trying a few things?
  • Move the useEmulator block after you change the firestore settings / enable persistence
  • Where you're doing firebase.firestore().enablePersistence(), instead do firebaseStore.enablePersistence()
If that doesn't work you could try explicitly setting "host: localhost:8080" and "ssl: false" in the Firestore settings, but you shouldn't need to do that.

- Sam

Roger Hopkins

unread,
Jun 30, 2021, 12:20:32 PM6/30/21
to fireba...@googlegroups.com

Thanks Sam!

 

That did it (the bulleted solution).

Sam Stern

unread,
Jun 30, 2021, 12:24:34 PM6/30/21
to fireba...@googlegroups.com
Glad that worked! I'll forward this one to one of the SDK engineers so we can find out why those changes worked, as they shouldn't matter.

- Sam

Sam Stern

unread,
Jun 30, 2021, 1:01:27 PM6/30/21
to fireba...@googlegroups.com
Just had one of the engineers explain this to me. The bug was here:


firebaseStore.settings({
  // ssl: false,
  ignoreUndefinedProperties: true
});

 This implicitly overrides the host setting. You could instead merge settings by specifying "merge: true".  Very recently we changed the SDK to display a warning  about this: https://github.com/firebase/firebase-js-sdk/pull/4925

- Sam

Reply all
Reply to author
Forward
0 new messages