Android で GitHub を使用して認証する

ウェブベースの汎用 OAuth ログインをアプリに統合し、Firebase SDK を使用してエンドツーエンドのログインフローを実行することで、ユーザーが Firebase での認証に GitHub アカウントを使用できるようになります。

始める前に

GitHub アカウントを使用してユーザーをログインさせるには、まず Firebase プロジェクトのログイン プロバイダとして GitHub を有効にする必要があります。

  1. まだ Firebase を Android プロジェクトに追加していない場合は追加します。

  2. Firebase コンソールで [Auth] セクションを開きます。
  3. [Sign-in method] タブで、[GitHub] プロバイダを有効にします。
  4. そのプロバイダのデベロッパー コンソールで取得したクライアント IDクライアント シークレットをプロバイダ構成に追加します。
    1. GitHub でデベロッパー アプリケーションとしてアプリを登録し、アプリの OAuth 2.0 クライアント IDクライアント シークレットを取得します。
    2. GitHub アプリの構成にあるアプリ設定ページで、Firebase OAuth リダイレクト URImy-app-12345.firebaseapp.com/__/auth/handler など)を認可コールバック URL として設定します。
  5. [保存] をクリックします。
  6. モジュール(アプリレベル)の Gradle ファイル(通常は <project>/<app-module>/build.gradle.kts または <project>/<app-module>/build.gradle)に、Android 用 Firebase Authentication ライブラリの依存関係を追加します。ライブラリのバージョニングの制御には、Firebase Android BoM を使用することをおすすめします。

    dependencies {
        // Import the BoM for the Firebase platform
        implementation(platform("com.google.firebase:firebase-bom:33.7.0"))
    
        // Add the dependency for the Firebase Authentication library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation("com.google.firebase:firebase-auth")
    }

    Firebase Android BoM を使用すると、アプリは常に互換性のあるバージョンの Firebase Android ライブラリを使用します。

    (代替方法)BoM を使用せずに Firebase ライブラリの依存関係を追加する

    Firebase BoM を使用しない場合は、依存関係の行でそれぞれの Firebase ライブラリのバージョンを指定する必要があります。

    アプリで複数の Firebase ライブラリを使用する場合は、すべてのバージョンの互換性を確保するため、BoM を使用してライブラリのバージョンを管理することを強くおすすめします。

    dependencies {
        // Add the dependency for the Firebase Authentication library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation("com.google.firebase:firebase-auth:23.1.0")
    }
    Kotlin 固有のライブラリ モジュールをお探しの場合、 2023 年 10 月(Firebase BoM 32.5.0)以降、Kotlin と Java のどちらのデベロッパーもメイン ライブラリ モジュールを利用できるようになります(詳しくは、このイニシアチブに関するよくある質問をご覧ください)。

  7. アプリの SHA-1 フィンガープリントを指定していない場合は、Firebase コンソールの [設定] ページで指定します。アプリの SHA-1 フィンガープリントを取得する方法の詳細については、クライアントの認証をご覧ください。

Firebase SDK を使用したログインフローの処理

Android アプリをビルドする場合、GitHub アカウントを使用して Firebase でユーザーを認証する最も簡単な方法は、Firebase Android SDK でログインフロー全体を処理することです。

Firebase Android SDK でログインフローを処理する手順は次のとおりです。

  1. プロバイダ ID github.comBuilder を使用して、OAuthProvider のインスタンスを構築します。

    Kotlin

    val provider = OAuthProvider.newBuilder("github.com")

    Java

    OAuthProvider.Builder provider = OAuthProvider.newBuilder("github.com");

  2. 省略可: OAuth リクエストと一緒に送信したい追加のカスタム OAuth パラメータを指定します。

    Kotlin

    // Target specific email with login hint.
    provider.addCustomParameter("login", "your-email@gmail.com")

    Java

    // Target specific email with login hint.
    provider.addCustomParameter("login", "your-email@gmail.com");

    GitHub がサポートするパラメータについては、GitHub の OAuth に関するドキュメントをご覧ください。setCustomParameters() で Firebase の必須パラメータを渡すことはできません。該当するパラメータは、client_idresponse_typeredirect_uristatescoperesponse_mode です。

  3. 省略可: 認証プロバイダにリクエストする、基本的なプロフィール以外の追加の OAuth 2.0 スコープを指定します。アプリケーションで GitHub API から限定公開のユーザーデータへのアクセスが必要な場合は、GitHub のデベロッパー コンソールの [API Permissions] で、GitHub API にアクセスする権限をリクエストする必要があります。リクエストされた OAuth スコープは、アプリの API 権限で事前構成されたものと完全に一致している必要があります。

    Kotlin

    // Request read access to a user's email addresses.
    // This must be preconfigured in the app's API permissions.
    provider.scopes = listOf("user:email")

    Java

    // Request read access to a user's email addresses.
    // This must be preconfigured in the app's API permissions.
    List<String> scopes =
            new ArrayList<String>() {
                {
                    add("user:email");
                }
            };
    provider.setScopes(scopes);

  4. OAuth プロバイダ オブジェクトを使用して Firebase での認証を行います。こうすると、他の FirebaseAuth オペレーションとは異なり、Chrome カスタムタブをポップアップして UI を制御することになります。その結果、アタッチした OnSuccessListenerOnFailureListener は UI が起動されるとすぐにデタッチされるため、そこからアクティビティを参照しないでください。

    最初に、レスポンスをすでに受け取っているかどうかを確認してください。この方法でログインすると、アクティビティがバックグラウンドになるため、ログインフロー中にシステムによってアクティビティが再要求される可能性があります。こうした場合にユーザーに再試行させないようにするために、結果がすでに存在するかどうかを確認する必要があります。

    保留中の結果があるかどうかを確認するには、getPendingAuthResult を呼び出します。

    Kotlin

    val pendingResultTask = firebaseAuth.pendingAuthResult
    if (pendingResultTask != null) {
        // There's something already here! Finish the sign-in for your user.
        pendingResultTask
            .addOnSuccessListener {
                // User is signed in.
                // IdP data available in
                // authResult.getAdditionalUserInfo().getProfile().
                // The OAuth access token can also be retrieved:
                // ((OAuthCredential)authResult.getCredential()).getAccessToken().
                // The OAuth secret can be retrieved by calling:
                // ((OAuthCredential)authResult.getCredential()).getSecret().
            }
            .addOnFailureListener {
                // Handle failure.
            }
    } else {
        // There's no pending result so you need to start the sign-in flow.
        // See below.
    }

    Java

    Task<AuthResult> pendingResultTask = firebaseAuth.getPendingAuthResult();
    if (pendingResultTask != null) {
        // There's something already here! Finish the sign-in for your user.
        pendingResultTask
                .addOnSuccessListener(
                        new OnSuccessListener<AuthResult>() {
                            @Override
                            public void onSuccess(AuthResult authResult) {
                                // User is signed in.
                                // IdP data available in
                                // authResult.getAdditionalUserInfo().getProfile().
                                // The OAuth access token can also be retrieved:
                                // ((OAuthCredential)authResult.getCredential()).getAccessToken().
                                // The OAuth secret can be retrieved by calling:
                                // ((OAuthCredential)authResult.getCredential()).getSecret().
                            }
                        })
                .addOnFailureListener(
                        new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                // Handle failure.
                            }
                        });
    } else {
        // There's no pending result so you need to start the sign-in flow.
        // See below.
    }

    ログインフローを開始するには、startActivityForSignInWithProvider を呼び出します。

    Kotlin

    firebaseAuth
        .startActivityForSignInWithProvider(activity, provider.build())
        .addOnSuccessListener {
            // User is signed in.
            // IdP data available in
            // authResult.getAdditionalUserInfo().getProfile().
            // The OAuth access token can also be retrieved:
            // ((OAuthCredential)authResult.getCredential()).getAccessToken().
            // The OAuth secret can be retrieved by calling:
            // ((OAuthCredential)authResult.getCredential()).getSecret().
        }
        .addOnFailureListener {
            // Handle failure.
        }

    Java

    firebaseAuth
            .startActivityForSignInWithProvider(/* activity= */ this, provider.build())
            .addOnSuccessListener(
                    new OnSuccessListener<AuthResult>() {
                        @Override
                        public void onSuccess(AuthResult authResult) {
                            // User is signed in.
                            // IdP data available in
                            // authResult.getAdditionalUserInfo().getProfile().
                            // The OAuth access token can also be retrieved:
                            // ((OAuthCredential)authResult.getCredential()).getAccessToken().
                            // The OAuth secret can be retrieved by calling:
                            // ((OAuthCredential)authResult.getCredential()).getSecret().
                        }
                    })
            .addOnFailureListener(
                    new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            // Handle failure.
                        }
                    });

    正常に完了すると、プロバイダに関連付けられている OAuth アクセス トークンを、返された OAuthCredential オブジェクトから取得できます。

    OAuth アクセス トークンを使用して、GitHub API を呼び出せます。

    たとえば、基本的なプロフィール情報を取得するには、Authorization ヘッダーにアクセス トークンを渡して REST API を呼び出します。

  5. 上記の例ではログインフローを中心に説明していますが、startActivityForLinkWithProvider を使用して GitHub プロバイダを既存のユーザーにリンクすることもできます。たとえば、複数のプロバイダを同じユーザーにリンクして、どれでもログインできるようにすることができます。

    Kotlin

    // The user is already signed-in.
    val firebaseUser = firebaseAuth.currentUser!!
    firebaseUser
        .startActivityForLinkWithProvider(activity, provider.build())
        .addOnSuccessListener {
            // Provider credential is linked to the current user.
            // IdP data available in
            // authResult.getAdditionalUserInfo().getProfile().
            // The OAuth access token can also be retrieved:
            // authResult.getCredential().getAccessToken().
            // The OAuth secret can be retrieved by calling:
            // authResult.getCredential().getSecret().
        }
        .addOnFailureListener {
            // Handle failure.
        }

    Java

    // The user is already signed-in.
    FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
    
    firebaseUser
            .startActivityForLinkWithProvider(/* activity= */ this, provider.build())
            .addOnSuccessListener(
                    new OnSuccessListener<AuthResult>() {
                        @Override
                        public void onSuccess(AuthResult authResult) {
                            // Provider credential is linked to the current user.
                            // IdP data available in
                            // authResult.getAdditionalUserInfo().getProfile().
                            // The OAuth access token can also be retrieved:
                            // authResult.getCredential().getAccessToken().
                            // The OAuth secret can be retrieved by calling:
                            // authResult.getCredential().getSecret().
                        }
                    })
            .addOnFailureListener(
                    new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            // Handle failure.
                        }
                    });

  6. 同じパターンを startActivityForReauthenticateWithProvider でも使用できます。これは、ログインしてから短時間のうちに行うべき機密性の高い操作のために、最新の認証情報を取得するのに使われます。

    Kotlin

    // The user is already signed-in.
    val firebaseUser = firebaseAuth.currentUser!!
    firebaseUser
        .startActivityForReauthenticateWithProvider(activity, provider.build())
        .addOnSuccessListener {
            // User is re-authenticated with fresh tokens and
            // should be able to perform sensitive operations
            // like account deletion and email or password
            // update.
        }
        .addOnFailureListener {
            // Handle failure.
        }

    Java

    // The user is already signed-in.
    FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
    
    firebaseUser
            .startActivityForReauthenticateWithProvider(/* activity= */ this, provider.build())
            .addOnSuccessListener(
                    new OnSuccessListener<AuthResult>() {
                        @Override
                        public void onSuccess(AuthResult authResult) {
                            // User is re-authenticated with fresh tokens and
                            // should be able to perform sensitive operations
                            // like account deletion and email or password
                            // update.
                        }
                    })
            .addOnFailureListener(
                    new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            // Handle failure.
                        }
                    });

次のステップ

ユーザーが初めてログインすると、新しいユーザー アカウントが作成され、ユーザーがログイン時に使用した認証情報(ユーザー名とパスワード、電話番号、または認証プロバイダ情報)にアカウントがリンクされます。この新しいアカウントは Firebase プロジェクトの一部として保存され、ユーザーのログイン方法にかかわらず、プロジェクトのすべてのアプリでユーザーを識別するために使用できます。

  • アプリでは、FirebaseUser オブジェクトからユーザーの基本的なプロフィール情報を取得できます。ユーザーを管理するをご覧ください。

  • Firebase Realtime DatabaseCloud Storageセキュリティ ルールでは、ログイン済みユーザーの一意のユーザー ID を auth 変数から取得し、それを使用して、ユーザーがアクセスできるデータを制御できます。

既存のユーザー アカウントに認証プロバイダの認証情報をリンクすることで、ユーザーは複数の認証プロバイダを使用してアプリにログインできるようになります。

ユーザーのログアウトを行うには、signOut を呼び出します。

Kotlin

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();