Firebase AuthenticationでGoogleアカウントによるログインを実装するのは簡単ですが、デフォルトだと全てのGoogleアカウントでログインできるようになっています。
社内向けのアプリケーションなどでは、特定のドメインのユーザーのみアクセスを許可したいケースがあると思いますが、そのようなケースの実装方法が案外出回っていなかったので、まとめておきます。
検証環境
- Angular6
- @angular/fire: v5.0.2
- firebase: v5.4.1
今回はAngularを例にしていますが、他のフレームワークでも大きな違いはないと思います。
AngularFire
AngularでFirebaseを使うには、AngularFireという公式のライブラリを使うのが一番早いです。
AngularFireのセットアップとAuthenticationの基本的な実装方法は以下を参照。
フロントエンドでの制御
例として、AuthServiceというclassに googleLogin()
というメソッドを実装しました。
GoogleAuthProviderをnewした後、setCustomParameters()
で hd
というパラメータにドメインを指定することで、Googleログインのポップアップで、指定したドメインのメールアドレスしか入力できないようになります。
import { Injectable } from '@angular/core';
import { auth } from 'firebase/app';
import { AngularFireAuth } from '@angular/fire/auth';
import { AngularFirestore, AngularFirestoreDocument } from '@angular/fire/firestore';
@Injectable({
providedIn: 'root'
})
export class AuthService {
constructor(
private afAuth: AngularFireAuth,
private afStore: AngularFirestore
) {}
googleLogin() {
const provider = new auth.GoogleAuthProvider();
provider.setCustomParameters({
hd: 'yourdomain.com'
});
return this.afAuth.auth.signInWithPopup(provider)
.then(credential => {
// Update user document in Firestore (おまけ)
this.updateUser(credential.user);
});
}
private updateUser(user: firebase.User) {
const userRef: AngularFirestoreDocument<any> = this.afStore.doc(`users/${user.uid}`);
const data = {
uid: user.uid,
email: user.email,
displayName: user.displayName,
photoURL: user.photoURL
};
return userRef.set(data, { merge: true });
}
}
googleLogin()
がコールされると、以下のようなポップアップが表示されます。
ちなみに、ログイン情報はブラウザのIndexedDBに保存されます。
サーバーサイド(Firestore)での制御
フロントエンドでの制御だけだと完璧ではないので、サーバーサイド(Firestore)でも、特定のドメインのユーザーしかアクセスできないように設定します。
Firestore Security Rules
Firestoreのセキュリティルールで、特定のドメインのユーザーしかドキュメントにアクセスできないようにします。
firebase init
でFirestoreを使うように設定しているプロジェクトだと、プロジェクトのディレクトリ直下に firebase.json
と firestore.rules
があると思います。
firestore.rules
に以下のルールを追加することで、yourdomain.com
ドメインのユーザー以外は全てのドキュメントにアクセスできないようになります。
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if isValidUser();
}
}
function isValidUser() {
return request.auth.uid != null && request.auth.token.email.matches('.*@yourdomain.com');
}
}
シミュレータでテスト
設定したルールが意図した動きをするかどうか、Firebase Consoleのシミュレータでテストできるので、ルールをデプロイする前に一度テストすることをオススメします。
ルールをデプロイ
$ firebase deploy --only firestore:rules