web-dev-qa-db-fra.com

Comment verrouiller la base de données Firebase à tout utilisateur d'un domaine (e-mail) spécifique?

J'ai une petite application Web Firebase personnelle qui utilise la base de données Firebase. Je veux sécuriser (verrouiller) cette application à n'importe quel utilisateur à partir d'un seul domaine spécifique. Je souhaite m'authentifier auprès de Google. Je ne sais pas comment configurer les règles pour dire "uniquement les utilisateurs d'un seul domaine spécifique (par exemple @foobar.com) peut lire et écrire dans cette base de données ".

(Une partie du problème que je vois: il est difficile de bootstrap une base de données avec suffisamment d'informations pour faire fonctionner ce cas d'utilisation. J'ai besoin de connaître l'e-mail de l'utilisateur au moment de l'authentification, mais auth l'objet ne contient pas de courrier électronique. Il semble que ce soit un problème d'œuf de poule, car j'ai besoin d'écrire des règles Firebase qui font référence aux données dans la base de données, mais ces données n'existent pas encore car mon utilisateur ne peut pas écrire dans la base de données.)

Si auth avait un e-mail, je pourrais facilement écrire les règles.

Merci d'avance!

22
Seth Ladd

Si vous utilisez la nouvelle Firebase, cela est désormais possible, car le email est disponible dans les règles de sécurité.

Dans les règles de sécurité, vous pouvez accéder à la fois à l'adresse e-mail et à sa vérification, ce qui rend possible certains cas d'utilisation intéressants. Avec ces règles par exemple, seul un utilisateur gmail authentifié et vérifié peut écrire son profil:

{
  "rules": {
    ".read": "auth != null",
    "gmailUsers": {
      "$uid": {
        ".write": "auth.token.email_verified == true && 
                   auth.token.email.matches(/.*@gmail.com$/)"
      }
    }
  }
}

Vous pouvez entrer ces règles dans la console de base de données Firebase de votre projet.

41
Frank van Puffelen

AVERTISSEMENT: ne faites pas confiance à cette réponse. Juste ici pour la discussion.

tldr: Je ne pense pas que ce soit possible, sans exécuter votre propre serveur.

Voici ma tentative jusqu'à présent:

{
  "rules": {
    ".read": "auth.provider === 'google' && root.child('users').child(auth.uid).child('email').val().endsWith('@foobar.com')",
    ".write": "auth.provider === 'google' && root.child('users').child(auth.uid).child('email').val().endsWith('@foobar.com')",
    "users": {
      "$user_id": {
        ".write": "auth.provider === 'google' && $user_id === auth.uid && newData.child('email').val().endsWith('@foobar.com')"
      }
    }
  }
}

Je crois que ce qui précède dit "n'autoriser les gens à créer un nouvel utilisateur que s'ils sont authentifiés par Google, essaient d'écrire dans le nœud de base de données pour eux-mêmes ($user_id === auth.uid) et leur e-mail se termine sur foobar.com ".

Cependant, un problème a été signalé: tout client Web peut facilement modifier son e-mail (à l'aide de la console de développement) avant d'envoyer le message à Firebase. Nous ne pouvons donc pas faire confiance aux données de l'entrée utilisateur lorsqu'elles sont stockées dans Firebase.

Je pense que la seule chose à laquelle nous pouvons réellement faire confiance est l'objet auth dans les règles. Cet objet auth est rempli par le backend de Firebase. Et, malheureusement, l'objet auth n'inclut pas l'adresse e-mail.

Pour mémoire, j'insère mon utilisateur de cette façon:

function authDataCallback(authData) {
  if (authData) {
    console.log("User " + authData.uid + " is logged in with " + authData.provider + " and has displayName " + authData.google.displayName);
    // save the user's profile into the database so we can list users,
    // use them in Security and Firebase Rules, and show profiles
    ref.child("users").child(authData.uid).set({
      provider: authData.provider,
      name: getName(authData),
      email: authData.google.email
    });

Comme vous pouvez l'imaginer, un utilisateur déterminé pourrait écraser la valeur de email ici (en utilisant les DevTools, par exemple).

2
Seth Ladd

Voici le code qui fonctionne bien avec ma base de données, j'ai établi une règle selon laquelle seuls les e-mails de ma société peuvent lire et écrire des données de ma base de données Firebase.

{
  "rules": {
    ".read": "auth.token.email.matches(/.*@yourcompany.com$/)",


        ".write": "auth.token.email.matches(/.*@yourcompany.com$/)"
      }
    }
1
Rishi

Pour tous ceux qui ne veulent vraiment pas se connecter à des comptes non vérifiés. Peut-être sale, mais très efficace.

Voici ma solution (application angulaire):

this.userService.login(this.email.value, this.password.value).then(data => {
  if (data.user.emailVerified === true) {
    //user is allowed
  } else {
    //user not allowed, log them out immediatly
    this.userService.logout();
  }
}).catch(error => console.log(error));
0
Michelangelo

Code qui fonctionne pour moi.

export class AuthenticationService {

    user: Observable<firebase.User>;

    constructor(public afAuth: AngularFireAuth) {
        this.user = afAuth.authState;
    }

    login(){
        var provider = new firebase.auth.GoogleAuthProvider();
        provider.setCustomParameters({'hd': '<your domain>'});
        this.afAuth.auth.signInWithPopup(provider)
        .then(response => {
            let token = response.credential.accessToken;
            //Your code. Token is now available.
        })
    }
}
0
Shirish