I am trying to authenticate a user in my app. I have a login screen that takes an email and password and then runs this:
login2(email: string, password: string): Observable<any> {
const signInObs: Observable<UserCredential> = from(this.fAuth.signInWithEmailAndPassword(email, password));
return signInObs.pipe(take(1), catchError(this.handleError), mergeMap((result: UserCredential) => {
console.log(`done this ONE... ${result.user.uid}`);
return this.firestore.collection('users').doc(result.user.uid).get().pipe(catchError(this.handleError), mergeMap((doc: DocumentSnapshot<any>) => {
console.log(`done this two... ${doc.data().name}`);
return result.user.getIdTokenResult(true).then((token: IdTokenResult) => {
// authenticate the user in the code
console.log(`done this three.. ${token.claims.admin}`);
this.handleAuthentication(
result.user.email,
result.user.uid,
doc.data().name,
token.claims.admin,
token.token
);
}).catch(error => {
throw new Error(error);
});
}));
}));
}
But the old ERROR FirebaseError: Missing or insufficient permissions. error happens with respect to the this.firebase.collection('users').doc(result.user.uid).get() part. This is all works just fine without that section - i.e. it logs in, gives me a token and so on. Everything works fine except it wont allow me to access that user record...
The rules in my database are:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// match logged in user doc in users collection
match /users/{userId} {
allow create: if request.auth.uid != null;
allow read: if request.auth != null && request.auth.uid == userId;
}
// match docs in the users collection
match /users/{userId} {
allow read, write: if request.auth.uid != null;
}
}
}
In reference to a reply that suggested it might be that FireAuth and Firestore modules aren't communicating correctly, this is how the app.module looks. These are all the references to the angular fire module in the app.module.
import { environment } from 'src/environments/environment';
import { AngularFireModule } from '@angular/fire';
import { AngularFireFunctions } from '@angular/fire/functions';
import { AngularFireAuthModule } from '@angular/fire/auth';
import { AngularFirestoreModule } from '@angular/fire/firestore';
@NgModule({
declarations: [
// just components
],
imports: [
// other imports
AngularFireModule.initializeApp(environment.firebaseConfig),
AngularFirestoreModule,
AngularFireAuthModule
],
providers: [
{provide: HTTP_INTERCEPTORS, useClass: AuthInterceptorService, multi: true},
AuthenticationService,
AngularFireFunctions
],
bootstrap: [AppComponent]
})
export class AppModule { }
And the constructor in the Authentication service:
constructor(private fAuth: AngularFireAuth,
private firestore: AngularFirestore,
private router: Router) {
}
I have tried running the id through the emulator and it seems like it should work. I have logged the userid from the login and it's identical to the document name it should be seeking.
This all seems like it should work but it doesn't. I have read a bunch of tutorials and none do anything hugely different - and differents are inconsistent between the tutorials.
I recognize the code isn't perfect in how it's written yet but wanted to make it functional first.
My data structure in the database looks like this:
The ID of the documents is the user id of the relevant person, I double-checked they all are correct.
Double-checking it works otherwise if I allow universal read-write then everything works just fine... it's only when those rules come in that they don't work.
