Search code examples
angularangularfire2

AngularFire Missing or insufficient permissions on login, works after refresh


I have a very standard Angular 12 application where a user logs in with Firestore and can then perform CRUD operations over their own documents.

As soon as you login to the application it throws

core.mjs:6495 ERROR FirebaseError: Missing or insufficient permissions.
    at index.esm2017.js:4327
    at ns (index.esm2017.js:4325)
    at to.onMessage (index.esm2017.js:11273)
    at index.esm2017.js:11227
    at index.esm2017.js:11250
    at index.esm2017.js:15093
    at index.esm2017.js:15126
    at ZoneDelegate.invoke (zone.js:372)
    at Object.onInvoke (core.mjs:25853)
    at ZoneDelegate.invoke (zone.js:371)

and no documents are loaded. However if I just refresh the page the error goes away and the documents load as expected.

My auth service is very standard

@Injectable({
  providedIn: "root"
})
export class AuthService {
  
  constructor(private angularFireAuth: AngularFireAuth, private router: Router) {

  }

  public login() {
    signInWithPopup(getAuth(), new GithubAuthProvider())
      .then(() => {
        this.router.navigate(["/"]);
      })
      .catch((error) => {
        console.log(error);
      });
  }
}

I'm trying to load the Firestore documents in a RepositoryService

@Injectable({
  providedIn: "root"
})
export class RepositoryService {

  repositories$: BehaviorSubject<Repository[]> = new BehaviorSubject<Repository[]>([]);

  constructor(private angularFireAuth: AngularFireAuth, private firestore: AngularFirestore) {
    this.angularFireAuth.authState.subscribe(authUser => {
      if (authUser) {
        this.firestore
          .collection("user")
          .doc(authUser.uid)
          .collection<Repository>("repositories")
          .valueChanges()
          .subscribe(this.repositories$);
      }
    });
  }
}

Is a different instants of AngularFireAuth being used here or something?

What's interesting is if I sign out, then refresh the page and log back in things work as expected. However signing out and straight back in again causes the Missing or insufficient permissions exception to be thrown.


Solution

  • I was able to solve the error by replacing the standard subscription with a switchMap

    constructor(
      private angularFireAuth: AngularFireAuth,
      private firestore: AngularFirestore,
    ) {
      this.angularFireAuth.authState
        .pipe(
          switchMap((authUser) =>
            authUser
              ? this.firestore.collection('user').doc(authUser.uid).collection<Repository>('repositories').valueChanges()
              : of([])
          )
        )
        .subscribe(this.repositories$);
    }
    

    I think the root of the problem was with the firebase listener trying to fetch documents during/after the logout process which was causing it to error out.

    This would explain why refreshing the page between login sessions solves.

    Awkward.