web-dev-qa-db-ja.com

Firebase Databaseを特定の(メール)ドメインのユーザーにロックダウンするにはどうすればよいですか?

Firebase Databaseを使用する小さな個人用Firebase Webアプリがあります。単一の特定のドメインのすべてのユーザーに対してこのアプリを保護(ロックダウン)したい。 Googleで認証したい。 「単一の特定ドメインのユーザーのみ(たとえば@foobar.com)このデータベースの読み取りと書き込みが可能です。」.

(私が目にする問題の一部:bootstrapこのユースケースを機能させるのに十分な情報を持つデータベース。認証時にユーザーのメールアドレスを知る必要があるが、authオブジェクトには電子メールが含まれていません。データベース内のデータを参照するFirebaseルールを記述する必要があるため、チキンエッグの問題のようですが、ユーザーができないため、そのデータはまだ存在しませんデータベースに書き込みます。)

authにメールがあれば、ルールを簡単に書くことができます。

前もって感謝します!

22
Seth Ladd

新しいFirebaseを使用している場合、emailがセキュリティルールで利用できるため、これが可能になりました。

セキュリティルールでは、メールアドレスと検証済みかどうかの両方にアクセスできるため、優れたユースケースが可能になります。たとえば、これらのルールでは、認証され、検証されたGmailユーザーのみがプロファイルを作成できます。

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

これらのルールは、プロジェクトの Firebase Databaseコンソール に入力できます。

41

警告:この答えは信用しないでください。議論のためだけにここに。

tldr:独自のサーバーを実行しなければ、可能だとは思いません。

これまでの私の試みは次のとおりです。

{
  "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')"
      }
    }
  }
}

上記のことは、「Googleによって認証され、自分のためにデータベースノードに書き込もうとしている場合にのみ、新しいユーザーの作成を許可する($user_id === auth.uid)そしてそのメールはfoobar.comで終わります。

ただし、問題が指摘されました。Webクライアントは、メッセージがFirebaseに送信される前に、(開発コンソールを使用して)メールを簡単に変更できます。そのため、Firebaseに保存されたユーザーエントリのデータを信頼することはできません。

実際に信頼できるのは、ルール内のauthオブジェクトだけだと思います。そのauthオブジェクトには、Firebaseのバックエンドが入力されます。そして、残念ながら、authオブジェクトにはメールアドレスが含まれていません。

記録のために、私はこの方法でユーザーを挿入しています:

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
    });

想像できるかもしれませんが、決心したユーザーはここでemailの値を上書きできます(たとえば、DevToolsを使用して)。

2
Seth Ladd

ここに私のデータベースでうまく機能するコードがあります、私は会社のメールだけが私のfirebaseデータベースのデータを読み書きできるというルールを設定しました。

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


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

未検証のアカウントでログインすることを本当に望んでいない人のために。たぶん汚れているが、非常に効果的です。

これは私の回避策です(Angularアプリ):

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

私のために働いているコード。

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