前回までで、
今回も、
Firebaseを適切に設定することで、
- メールアドレスとパスワードを使ってログイン処理を行う
- チャットメッセージは適切にログインしたユーザしか閲覧もメッセージの投稿もできない
といったよくある機能を簡単に実現することができます。
ユーザ認証とアクセス制御
Authentication(認証)
「セキュリティ」
- 「Aさんは
/messages/を閲覧できる」01 - 「Bさんは
/messages/を閲覧・02 書き込みできる」
といったアクセス制御が可能です。
この
Firebaseは次の表にある認証方法を提供しており、
| 認証の種類 | 概要 |
|---|---|
| 大手SNS認証 | Facebook, GitHub, Google, Twitter アカウントを使った認証 |
| パスワード認証 | Firebase自身にEメール、 |
| 匿名ログイン | 一時的な匿名ログイン |
| カスタムログイントークン | すでに自前で持っている認証基盤との連携 |
今回は、
今後の連載中では、
Authorization(認可)
ユーザ認証によって、
Firebaseではこの認可情報でユーザを識別し、
たとえば、/fooは誰でも閲覧できるが、
{
"rules": {
"foo": {
".read": true,
".write": false
}
}
}
パスワード認証
今回の連載では、
パスワード認証を利用するには、
これで準備は整いました。
さっそくFirebase上にユーザを作成するコードを見て行きましょう。
ユーザの作成
まずは以下のコードを実行してみてください。
Firebase ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
ref.createUser("fu.shiroyama@gmail.com", "abcd1234", new Firebase.ValueResultHandler<Map<String, Object>>() {
@Override
public void onSuccess(Map<String, Object> result) {
Log.d(TAG, "Successfully created user account with uid: " + result.get("uid"));
}
@Override
public void onError(FirebaseError firebaseError) {
Log.d(TAG, "error: " + firebaseError.getMessage());
}
});
まず、
次に、createUser()メソッドを呼び出します。createUser()は第1引数にEメールアドレス、
認証の結果は、Firebase.インタフェースで受け取ることができます。成功した場合はonSuccess()の第1引数に認証結果がMap形式で渡されます。ここではユーザを一意に識別するuidを取得しています。
以下のようにログ出力されれば成功です。
D/Firebase: Successfully created user account with uid: 17613df6-4d51-4148-9adf-e948c6699b53
失敗した場合はonError()の第1引数にFirebaseError形式でエラーが渡されます。FirebaseErrorからはgetMessage()やgetDetail()でエラー理由を取得することができます。
たとえば、
D/Firebase: error: The specified email address is already in use.
登録済みユーザはダッシュボードから確認することができます。
uid
このuidは、uidをアプリで一意なユーザのユニークキーとして利用するのは正しい使い方です。
ユーザの認証
ユーザの作成ができたので、
パスワード認証にはauthWithPassword()メソッドを利用します。第1引数にEメールアドレス、Firebase.で受け取ります。
ref.authWithPassword("fu.shiroyama@gmail.com", "abcd1234", new Firebase.AuthResultHandler() {
@Override
public void onAuthenticated(AuthData authData) {
Log.d(TAG, "User ID: " + authData.getUid() + ", Provider: " + authData.getProvider());
Log.d(TAG, "expires: " + authData.getExpires());
}
@Override
public void onAuthenticationError(FirebaseError firebaseError) {
Log.d(TAG, "error: " + firebaseError.getMessage());
}
});
認証に成功すると、onAuthenticated()の第1引数にAuthDataオブジェクトが渡されます。以下のようにログ出力されれば成功です。
D/Firebase: User ID: 17613df6-4d51-4148-9adf-e948c6699b53, Provider: password
D/Firebase: expires: 1463468344
エラーはユーザ登録の時と同様、FirebaseError形式で受け取ります。以下は、
D/Firebase: error: The specified password is incorrect.
AuthData
AuthDataはさまざまな認可情報が詰まった非常に重要なデータです。AuthDataからは以下のような情報を取得することができます。
| プロパティ | 概要 |
|---|---|
uid | ユーザを一意に識別するID |
token | 認証トークン |
expires | 認証の有効期限を表現するUNIXタイム |
provider | 認証プロバイダ情報 |
他にも、
また、expiresの期限が過ぎるとこの認証は無効になってしまうため、
認証の解除
認証は、ref. メソッドを呼び出すことでいつでも失効させることができます。ユーザログアウト時等に利用することが考えられるでしょう。
アクセス制御
ここまでで、
アクセス制御は、
ここでは、/messagesを使い、
まず、rules直下の.readと.writeを両方ともfalseにします。
{
"rules": {
".read": false,
".write": false
}
}
Firebase Rulesは、falseにし、
次に、messagesに認証済みのユーザのみアクセス可能とします。認証済みのユーザは、uidという組み込み変数に必ず値が入るので、uid != nullとすることで認証済みのユーザかどうかを判定します。
{
"rules": {
".read": false,
".write": false
"messages": {
".read": "auth != null",
".write": "auth != null"
}
}
}
設定が終わったら、
試しに、/messagesの情報の取得を試み、
D/Firebase: onCancel: Permission denied
次に、
さまざまな組み込み変数
Firebase Rulesには、uid以外にもさまざまな組み込み変数が用意されており、
| 組み込み変数 | 概要 |
|---|---|
now | Firebaseサーバの現在時刻 |
root | Firebaseデータベースのrootパス |
newData | これから書き込まれるデータ |
data | 現在このパスに存在するデータ |
$variables | データのIDに動的にマッチする変数。後述 |
auth | 認証情報 |
この内、$variablesは非常によく使うので使い方を解説します。
$ variables
$variablesは、$に任意のアルファベットで変数名を付けるだけで、
たとえば、$user_は任意のユーザIDににマッチします。マッチさせたIDはアクセス制御に利用します。
{
"rules": {
"users": {
"$user_id": {
".write": "$user_id === auth.uid"
}
}
}
}
auth組み込み変数を使ってuidを比較し、uidを持つユーザが自分のuidと同じパスにアクセスした場合にのみデータの書き込みを許可しています。
組み込み変数と$variablesを組み合わせると、
今後の連載では実践テクニックとして細やかなアクセス制御のルールを公開予定です。楽しみにしていてください。
まとめ
今回の連載では、
さて、
