Help us understand the problem. What is going on with this article?

Firebase Authentication を調べてみた

More than 1 year has passed since last update.

概要

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とも連携しやすいので、サーバーレスでアプリを作るならかなり有用と感じました
sadashi
Androidエンジニアをやってます。 Kotlinとかソフトウェアアーキテクチャとかが好きです。 ちょっとだけSwiftでiOSのアプリも作ってました。
tabelog
お店選びで失敗したくない人のためのグルメサイト「食べログ」を開発しています
https://tabelog.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away