1

I want to restrict the users to be able to sign in in my Firestore application using the specific gmail domain. I found the similar question here but that is totally different from the Firestore. So let me explain my requirement what I want.

Suppose one company called abc.com are using the gmail services and they have integrated their all email accounts to gmail. So they can use gmail email services using that account. So I want to restrict to users that only use the username@abc.com gmail account to login to my firestore app.

I have searched a lot but didn't found any documentation about this.

Renaud Tarnec
  • 79,263
  • 10
  • 95
  • 121
Asif Mushtaq
  • 3,658
  • 4
  • 44
  • 80
  • 1
    Have a look at https://stackoverflow.com/questions/36943350/how-do-i-lock-down-firebase-database-to-any-user-from-a-specific-email-domain and https://stackoverflow.com/questions/24063435/firebase-simple-login-prevent-new-users?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa. You cannot restrict users to create an account but you can restrict who can access to the services (Firestore, Real Time Database, etc.) through security rules. See the doc about securing Firestore https://firebase.google.com/docs/firestore/security/get-started. See also – Renaud Tarnec Apr 23 '18 at 16:35
  • @RenaudTarnec that is restricting the user to write level, but I want to not be able to register or login using the other account. – Asif Mushtaq Apr 23 '18 at 17:21
  • @ Unknonw I do understand your need. The point is that if you use the standard email authentication of Firebase you cannot prevent anyone to sign in to your Firebase project with whatever email they want: i.e. they will appear in the list of users in the Firebase Console. It may seem weird but it is the model that was chosen by Firebase creators. The only think you can do is to protect your databases/services with security rules and allow only users with emails corresponding to the domain you wish. – Renaud Tarnec Apr 23 '18 at 18:38
  • @RenaudTarnec I'm using the Gmail authentication and I found `setHostedDomain` which I have tried but still not working as expected. – Asif Mushtaq Apr 23 '18 at 19:03
  • Ok I didn't get the fact you were using Gmail authentication. So, sorry and ... good luck! (As I don't think I can help you) – Renaud Tarnec Apr 23 '18 at 19:05

2 Answers2

7

There doesn't seem to be a solid Firestore solution for this but I have a compound solution:

  • A security rule on the first data collection accessed, where I check the email domain
  • A catchError on the data retrieval, where I check for error code 'permission-denied'
  • An error handler that will call the authentication service and force a logout with a redirect to an unauthorized page.

Sorry about pasting snippets, but I couldn't get the formatter to format all the code.

My component code:

  ngOnInit(): void {
    this.leadsDataSubscription = this.leadService.getLeadsSnapshot()
      .pipe(
        catchError((e: any) => Observable.throw(this.errorHandler(e)))
      )
      .subscribe(data => {
        this.leadsDataSource.data = data;
        this.leadsDataSource.paginator = this.paginator;
        this.leadsDataSource.sort = this.sort;
      });
    this.currentUser = this.authSvc.getCurrentUser();
  }

  private errorHandler(error: any) {
    if (error.name === 'FirebaseError' && error.code === 'permission-denied') {
      this.leadsDataSubscription.unsubscribe()
      this.authSvc.logout('/unauthorized');
    }
  }

My service code

  logout(redirectURL?: string) {
    this.unsubscribe()
    this.afAuth.auth.signOut()
      .then(response => {
        this.snackBar.open('Signed out');
        this.router.navigate([redirectURL || '/']);
      })
      .catch(error => this.snackBar.open('Error signing out: ' + error));
  }

And the Firestore rules:

match /leads/{document=**} {
  allow read: if isAllowedDomain() && isSignedIn();
  allow update: if isAllowedDomain() && isSignedIn() && canUpdate()
  allow delete: if isAllowedDomain() && isSignedIn() && isCreator() && canWrite() || isGod()
  allow create: if isAllowedDomain() && isSignedIn() && userExists();
}
function isAllowedDomain() {
    return request.auth.token.email_verified == true &&
               request.auth.token.email.matches(".*@workdomain.se") ||
               request.auth.token.email.matches(".*@privatedomain.org")
}
jsaddwater
  • 1,781
  • 2
  • 18
  • 28
0

You cannot restrict domains in email authentication or gmail authentication. This is the trade off you have to make when using third party like Firebase solution for authentication.

In case of gmail auth on android what you can do is first read gmail accounts available on device and then only show accounts if the domain matches. This way you can at least restrict user on UI level to have certain domain.

BUT beware the user can still do another domain login since firebase allows all gmail accounts to use authentication. You are only restricting the UI not the system

Umar Hussain
  • 3,461
  • 1
  • 16
  • 38