Skip to content
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

Angularfire2 shows “Missing permissions” error, whilst straight firebase runs with no issue #2121

Closed
adzza24 opened this issue Jun 26, 2019 · 14 comments

Comments

@adzza24
Copy link

adzza24 commented Jun 26, 2019

Version info

Angular: 6.0.3

**Firebase:**6.2.0

**AngularFire:**5.2.1

How to reproduce these conditions

To recreate the issue

In my AuthService

constructor(
  private afAuth: AdminAngularFireAuth,
  private afStore: AngularFirestore
) {
  this.user$ = this.afAuth.authState.pipe(switchMap((user: firebase.User) => {
    if (!user) {
      return of(null);
    }
    return this.afStore.collection("users").doc(user.authId).valueChanges()
  }));
}

This was working fine until I added the rules to firebase (see below). Now when requesting the user doc I get a Missing or insufficient permissions error.

I know what you'd think - my rules are inicorrect. But I have tested the rules in firebase using the simulator AND I have tested them using pure firebase from my front end app like this:

var email = "[email protected]";
var password = "xxx";
var firebaseConfig = {...};

firebase.initializeApp(firebaseConfig);

firebase.auth().onAuthStateChanged((u) => {
  if (u) {
    firebase.firestore().doc('users/' + u.uid).get()
      .then(u => console.log("Got favorites", u.data()));
    firebase.firestore().doc('favorites/' + u.uid).get()
      .then(u => console.log("Got favorites", u.data()));
  }
});

firebase.auth().signInWithEmailAndPassword(email, password).then(cred => {
  console.log("Signed in", cred)
})

This works. So it is not a firebase permissions issue, it is something that AngularFire is doing which pure firebase does not. If it makes any difference it seems to happen more after I have logged out with one user and then try to log back in with another, but no amount of cache/cookie clearing seems to help. Not even using a different browser. Just randomly a day later it might start working again, but then when I log out and back in again the same thing happens.

What sometimes happens is I log out of User1, login to User2. Then I logout of User2 and try to log back in to User1. Now the same user I was just logged into gets permissions error's access their documents. The authorisation is successful, but the subsequent request to a firestore document is denied. When only moments ago the exact same request was allowed. This has to be a bug... It feels like somewhere a reference is being stored to the session and not wiped. So even though the user has changes, maybe Anguarfire is sending old info in the request and thus it gets denied. I don't know how to test this or diagnose it though.

Sample data and security rules

Data structure:

{
    users: <Collection>{
        userId1: <Document>{
            firstName: "John",
            lastName: "Doe",
            authId: "userId1"
        }
    }
}

Security Rules:

service cloud.firestore {
    match /databases/{database}/documents {

        // Re-usable helper function to retrieve current user record
        function getUser() {
            return get(/databases/$(database)/documents/users/$(request.auth.uid))
        }

        match /users/{userID} {

            // Users can view/edit themselves
            allow read, write: if getUser().data.authId == userID;
      
            // Admins can view/edit anyone
            allow read, write: if getUser().data.role == 0;
        }
    }
}

Expected behavior

Documents should be accessible from the front end app via AngularFire2

Actual behavior

The request is denied with a Missing or insufficient permissions error, while pure firebase works...

@adzza24
Copy link
Author

adzza24 commented Jun 26, 2019

Note I tried reducing the complexity of my firebase rules to this:

match /{document=**} {
  allow read, write: if request.auth.uid != null;
}

I still get intermittent errors. I can log in, whilst someone I work with cannot, using the exact same credentials, just moments apart.

If I reduce the ruleset to this, then it works again, but this is obviously highly insecure:

match /{document=**} {
  allow read, write;
}

Again, it all works with straight firebase, but not when I plug in AngularFire2.

@adzza24
Copy link
Author

adzza24 commented Jul 26, 2019

I have since experienced this issue on another completely separate project, which has the lastest Firebase, Angular and AngularFire2 installed in it (as of July 2019). As this issue received 0 attention, I have created my own services around firebase and removed AngularFire2 from my projects entirely, which solves the issue. To me this is hard proof that the issue is with AngularFire2 and not firebase or my own rules or code around it. This is a security risk, and I can't imagine how many people (like me!) have just had to remove all their rules and make their firebase database open to the public in order to get it working with AngularFire2.

@david0178418
Copy link

I thought I had this issue as well, but it turned out I was incorrectly using mergeMap in one of my streams where I really wanted a switchMap:

mergeMap(u =>
  u ?
    db.doc<UserDoc>(`users/${u.uid}`).valueChanges() :
    of(null),
)

Since I was using "merge", the connection was kept alive. Correctly using switchMap removed this errror.

Is it possible you're hitting a similar issue in one of your streams?

@adzza24
Copy link
Author

adzza24 commented Feb 29, 2020

Unfortunately not - I have not a single mergeMap in that project. In the end I had to write my own wrapper around the Firebase Web API, and it all worked without changing any of my other code, so I think it's definitely a bug in the AngularFire library. Disappointed that I still haven't had an official response after all this time! I thought the library was supposed to be well maintained...

@tommyc38
Copy link

tommyc38 commented Jun 16, 2020

I am getting this error and have been searching for hours as to what might be causing it given it doesn't seem to be my rules (which I changed repeatedly).

I can confrim that reducing my rules to:

match /{document=**} { allow read, write; }

UPDATE: Nevermind...I found a tiny error in my rules, fixed it, and now everything is working properly.

@minimal-scouser
Copy link

Kind of a similar issue.
But mine is that on the first run it works fine but when I reload the page it throws the error.

FYI, I am setting persistence to session.

My workaround was that I had to call my query inside the subscribe method of any of the user checking methods like auth.user on AuthStateChanged(). Which means I had to first invoke the auth checking methods. So does that mean session persistence is not working?

@jamesdaniels
Copy link
Member

Closing as not AngularFire specific.

@pandabuilt
Copy link

@jamesdaniels I feel like this should be reopened. The people commenting had separate issues than the original poster.

@adzza24 did you ever figure out a solution?

@pandabuilt
Copy link

Okay, I have solved this for myself. It was my rules, not this package. I don't know if I can say the same for the original poster.

What took me for a loop was that the message is the same for errors as it is disallowed (design change?).

I did answer it: https://stackoverflow.com/questions/67388272/angular-firestore-rules-work-inside-of-firebase-firestore-rule-playground-but-no/67392057#67392057

@dalenguyen
Copy link

dalenguyen commented Jun 5, 2021

Having the same issuing. It works when security rules are public. If I applied authentication, it doesn't work at all.

"@angular/fire": "^6.1.5",
 "firebase": "^8.6.3",

Sample code:

    this.currentUser$ = this.afAuth.authState.pipe(
      switchMap((user) => {
        if (user) {
          // Missing permissions!!!
          return this.db.doc<User>(`users/${user.uid}`).valueChanges()
        }
        return of(null)
      }),

@adzza24
Copy link
Author

adzza24 commented Jun 7, 2021

The issue for me was that I had 2 instances of Firebase running. This should be totally fine, and is the (only?) way to allow an admin user to change the email or password of another user.

However, I S as AngularFire randomly defaults to the wrong instance of Firebase sometimes, I.e. the one without a user logged in, so it errors as of the user does not have permission.

This does seem to be a bug with AngularFire, as Firebase does not exhibit this behaviour when used on its own. There should be a way of specifying which instance of Firebase to use (or a method to retrieve the instance before making a call), but at the very least I would expect the default instance to be consistent, so that if there are 2 instances, all requests and logins run through the same one. In my case, login was defaulting to instance 1, whilst Firestore requests were intermittently (and seemingly randomly) running through the other instance.

With this in mind, @jamesdaniels I would suggest this needs to be reopened.

FYI, I could only resolve this by removing angular fire from my dependencies and writing my own wrapper around Firebase. The rest of my code and Firebase rules stayed exactly the same.

@ghost
Copy link

ghost commented Jul 15, 2021

Yes, @jamesdanielsm I am facing the same issue with @angular/fire. I am getting errors like 'FirebaseError: Missing or insufficient permissions' and 'FirebaseError: The caller does not have permission', even I am logged in using the following function:
this.afAuth.signInWithEmailAndPassword(email, password);

@jamesdaniels
Copy link
Member

@ganesh-august update firebase, there was a bug firebase/firebase-js-sdk#4932

@ghost
Copy link

ghost commented Jul 16, 2021

Thanks for the suggestion @jamesdaniels . I have installed the @angular/fire by using the following command and it worked perfectly.

npm install firebase @angular/fire --save

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

7 participants