概要

FirebaseのAuthenticationに関して調べてみました。
UIに関しては基本FirebaseUIのAndroid版を利用しています。
iOSやWEBに関しても提供されているので、他のプラットフォームでも利用できそうです。

特徴

認証の種類

  • Password
    • メールアドレスとパスワードでの認証
  • Provider
    • 下記のプロバイダでのユーザー認証
    • Google
    • Facebook
    • Twitter
    • GitHub
    • 各アカウントでのDeveloper登録等は必要
  • Phone Number
    • SMSを利用した認証
  • Custom
    • Firebase Consoleで鍵を生成し、それを使用した認証方式
  • Anonymous
    • 一時的な匿名の認証
    • 匿名アカウントから通常アカウントへのアップグレードは可能

アカウントの適用範囲について

  • 作成したアカウントはプロジェクト単位で共有される
    • 各プラットフォームで共通利用する場合は、同じプロジェクトにアプリを登録する必要がある

プロフィールの拡張について

  • ユーザー プロパティ
    • 固定の基本プロパティ以外を設定することはできない
    • 拡張したい場合はRealtime Database等を利用する必要がある

ユーザー管理について

  • Firebase Consoleでは以下の機能が利用できる
    • ユーザー追加
    • パスワードリセットメールの送信
    • アカウントの停止
    • アカウントの削除
  • 上記以外の操作をする場合はFirebase Admin SDKAdmin Auth APIを利用する必要がある
    • もちろん上記内容も実行できる
    • Node.jsJavaPythonで実行できる

Cloud Functions との連携

Authentication Flow Chart

機能

サインイン / サインアップ

private static final int REQUEST_CODE_AUTH = 100;

private void signIn() {
    startActivityForResult(
            AuthUI.getInstance()
                    .createSignInIntentBuilder()
                    .setAvailableProviders(
                            Arrays.asList(
                                    new AuthUI.IdpConfig.Builder(AuthUI.GOOGLE_PROVIDER).build(),
                                    new AuthUI.IdpConfig.Builder(AuthUI.FACEBOOK_PROVIDER).build(),
                                    new AuthUI.IdpConfig.Builder(AuthUI.TWITTER_PROVIDER).build(),
                                    new AuthUI.IdpConfig.Builder(AuthUI.EMAIL_PROVIDER).build()))
                    .setPrivacyPolicyUrl(getString(R.string.url_privacy_policy))
                    .setAllowNewEmailAccounts(true)
                    .build(),
            REQUEST_CODE_AUTH);
}
  • パスワード認証

    • メールアドレス入力後、既存ユーザーか判定し既存ユーザーの場合パスワード入力、新規ユーザーは登録画面に遷移する
  • setAvailableProviders()

    • IdpConfigのリストを渡すことで対応するAuth機能が使える
    • 上記例だと以下ようになる

sign_in_select_provider.png

  • setPrivacyPolicyUrl()
    • 設定することで、以下の画像のようにパスワード認証の新規登録画面でプライバシーポリシーのリンクが表示される

sign_up_password.png

  • setAllowNewEmailAccounts()
    • 新規メールアドレスの入力を許可するか否か

サインアウト

private void signOut() {
    AuthUI.getInstance()
            .signOut(this)
            .addOnCompleteListener(new OnCompleteListener<Void>() {
                public void onComplete(@NonNull Task<Void> task) {
                    if (task.isSuccessful()) {
                        Toast.makeText(AuthenticationActivity.this,
                                R.string.success_sign_out, Toast.LENGTH_SHORT).show();
                    }
                }
            });
}
  • サインインされている状態で実行すれば問題なし
  • 他のAPIも同様だが、OnCompleteListenerOnFailureListenerを登録することで結果をハンドリングできる

アカウント削除

private void deleteAccount() {
    FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
    if (user == null) {
        return;
    }

    user.delete()
            .addOnCompleteListener(new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    if (task.isSuccessful()) {
                        Toast.makeText(AuthenticationActivity.this,
                                R.string.success_delete_account, Toast.LENGTH_SHORT).show();
                    } else {
                        Exception ex = task.getException();
                        if (ex instanceof FirebaseException) {
                            Toast.makeText(AuthenticationActivity.this,
                                    R.string.do_re_authentication, Toast.LENGTH_SHORT).show();
                            reAuthSignIn(REQUEST_CODE_DELETE_RE_AUTH);
                        } else {
                            Toast.makeText(AuthenticationActivity.this,
                                    R.string.fail_delete_account, Toast.LENGTH_SHORT).show();
                        }
                    }
                }
            });
}
  • 上記はFirebaseUserのインスタンスから削除を実行する実装方法
    • FirebaseUIAuthUI.getInstance().delete(this);でも削除可能
  • 注意点
    • アカウント削除のようなセキュリティ上重要な操作を行う場合は、ユーザーが直近でサインインしている必要がある
    • サインインから時間が立っている場合は再認証の必要がある(reAuthSignIn()

再認証

private void reAuthSignIn() {
    FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
    if (user == null) {
        return;
    }

    List<AuthUI.IdpConfig> idpConfigs = new ArrayList<>();
    for (UserInfo info : user.getProviderData()) {
        String provider = info.getProviderId();
        if (provider.equals(FirebaseAuthProvider.PROVIDER_ID)) {
            continue;
        }
        idpConfigs.add(new AuthUI.IdpConfig.Builder(provider).build());
    }

    startActivityForResult(
            AuthUI.getInstance()
                    .createSignInIntentBuilder()
                    .setAvailableProviders(idpConfigs)
                    .setAllowNewEmailAccounts(false)
                    .build(),
            REQUEST_CODE_AUTH);
}
  • AuthUIには再認証のUIは提供されていない
    • そのため、ユーザーが利用しているプロバイダ名からサインインページへ遷移するようにした
  • 公式ドキュメントにはFirebaseUserreauthenticate()を利用したサンプルもある

ユーザープロフィール取得

ユーザープロフィール更新

  • こちらもサンプルは公式ドキュメントの通りなので省略
  • ユーザー再認証のドキュメントに記載があるが、再認証が必要なものは簡単に更新できないため、更新できるのは以下の項目のみとなる
    • 表示ユーザー名
    • プロフィール写真のURL

確認メール送信

  • Eメールアドレスへ確認メールを送信することができる

パスワードリセットメール送信

sign_in_input_password.png send_password_rest_mail.png

メールアドレスとパスワードの設定

まとめ

  • サンプルを見ての通りかなりお手軽に認証が組み込めます
  • Realtime DatabaseCloud Functionsとも連携しやすいので、サーバーレスでアプリを作るならかなり有用と感じました
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.