Google は、黒人コミュニティのための人種的公平の促進に取り組んでいます。詳細をご覧ください。

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

Firebase Authentication with Identity Platform にアップグレードした場合は、選択した OpenID Connect (OIDC) 準拠のプロバイダーを使用して、Firebase でユーザーを認証できます。これにより、Firebase でネイティブにサポートされていない ID プロバイダーを使用できるようになります。

あなたが始める前に

OIDC プロバイダーを使用してユーザーをサインインするには、最初にプロバイダーからいくつかの情報を収集する必要があります。

  • クライアント ID : アプリを識別するプロバイダー固有の文字列。プロバイダーは、サポートするプラットフォームごとに異なるクライアント ID を割り当てる場合があります。これは、プロバイダーによって発行された ID トークンのaudクレームの値の 1 つです。

  • クライアント シークレット: プロバイダーがクライアント ID の所有権を確認するために使用するシークレット文字列。クライアント ID ごとに、一致するクライアント シークレットが必要になります。 (この値は、強く推奨される認証コード フローを使用している場合にのみ必要です。)

  • Issuer : プロバイダーを識別する文字列。この値は、 /.well-known/openid-configurationを追加した場合にプロバイダーの OIDC ディスカバリー ドキュメントの場所となる URL である必要があります。たとえば、発行者がhttps://auth.example.comの場合、検出ドキュメントはhttps://auth.example.com/.well-known/openid-configurationで利用可能である必要があります。

上記の情報を入手したら、OpenID Connect を Firebase プロジェクトのサインイン プロバイダーとして有効にします。

  1. Android プロジェクトに Firebase を追加します

  2. Firebase Authentication with Identity Platform にアップグレードしていない場合は、アップグレードしてください。 OpenID Connect 認証は、アップグレードされたプロジェクトでのみ使用できます。

  3. Firebase コンソールの [サインイン プロバイダー] ページで、[新しいプロバイダーの追加] をクリックし、[ OpenID Connect ] をクリックします。

  4. 認証コード フローを使用するか、暗黙的な付与フローを使用するかを選択します。

    プロバイダーがサポートしている場合は、常にコード フローを使用する必要があります。暗黙的なフローは安全性が低く、使用しないことを強くお勧めします。

  5. このプロバイダーに名前を付けます。生成されたプロバイダー ID に注意してください: oidc.example-providerようなものです。アプリにサインイン コードを追加するときに、この ID が必要になります。

  6. クライアント ID とクライアント シークレット、およびプロバイダーの発行者文字列を指定します。これらの値は、プロバイダーが割り当てた値と正確に一致する必要があります。

  7. 変更を保存します。

Firebase SDK でログイン フローを処理する

Android アプリを構築している場合、OIDC プロバイダを使用して Firebase でユーザーを認証する最も簡単な方法は、Firebase Android SDK でログイン フロー全体を処理することです。

Firebase Android SDK でサインイン フローを処理するには、次の手順に従います。

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

    Kotlin+KTX

    val providerBuilder = OAuthProvider.newBuilder("oidc.example-provider")

    Java

    OAuthProvider.Builder providerBuilder = OAuthProvider.newBuilder("oidc.example-provider");

  2. オプション: OAuth 要求で送信する追加のカスタム OAuth パラメーターを指定します。

    Kotlin+KTX

    // Target specific email with login hint.
    providerBuilder.addCustomParameter("login_hint", "user@example.com")

    Java

    // Target specific email with login hint.
    providerBuilder.addCustomParameter("login_hint", "user@example.com");

    OIDC プロバイダーがサポートするパラメーターについては、OIDC プロバイダーに確認してください。 setCustomParameters()で Firebase に必要なパラメータを渡すことはできないことに注意してください。これらのパラメータはclient_idresponse_typeredirect_uristatescope 、およびresponse_modeです。

  3. オプション: 基本プロファイル以外に、認証プロバイダーに要求する追加の OAuth 2.0 スコープを指定します。

    Kotlin+KTX

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

    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("mail.read");
                    add("calendars.read");
                }
            };
    providerBuilder.setScopes(scopes);

    使用するスコープについては、OIDC プロバイダーに確認してください。

  4. OAuth プロバイダー オブジェクトを使用して Firebase で認証します。他の FirebaseAuth 操作とは異なり、これはCustom Chrome Tabをポップアップして UI を制御することに注意してください。そのため、アタッチしたOnSuccessListenerOnFailureListenerで Activity を参照しないでください。これらは、操作が UI を開始するとすぐにデタッチされます。

    最初に、すでに応答を受け取っているかどうかを確認する必要があります。この方法でサインインすると、Activity がバックグラウンドに置かれます。つまり、サインイン フロー中にシステムによって回収される可能性があります。これが発生した場合にユーザーに再試行させないようにするために、結果が既に存在するかどうかを確認する必要があります。

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

    Kotlin+KTX

    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+KTX

    firebaseAuth
        .startActivityForSignInWithProvider( /* activity = */this, 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.
                        }
                    });

  5. 上記の例はサインイン フローに焦点を当てていますが、 startActivityForLinkWithProvider を使用してstartActivityForLinkWithProviderプロバイダーを既存のユーザーにリンクすることもできます。たとえば、複数のプロバイダーを同じユーザーにリンクして、いずれかでサインインできるようにすることができます。

    Kotlin+KTX

    // The user is already signed-in.
    val firebaseUser = firebaseAuth.currentUser!!
    firebaseUser
        .startActivityForLinkWithProvider( /* activity = */this, 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+KTX

    // The user is already signed-in.
    val firebaseUser = firebaseAuth.currentUser!!
    firebaseUser
        .startActivityForReauthenticateWithProvider( /* activity = */this, 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.
                        }
                    });

サインイン フローを手動で処理する

アプリに OpenID Connect サインイン フローをすでに実装している場合は、ID トークンを直接使用して Firebase で認証できます。

Kotlin+KTX

val providerId = "oidc.example-provider" // As registered in Firebase console.
val credential = oAuthCredential(providerId) {
    setIdToken(idToken) // ID token from OpenID Connect flow.
}
Firebase.auth
    .signInWithCredential(credential)
    .addOnSuccessListener { authResult ->
        // User is signed in.

        // IdP data available in:
        //    authResult.additionalUserInfo.profile
    }
    .addOnFailureListener { e ->
        // Handle failure.
    }

Java

AuthCredential credential = OAuthProvider
        .newCredentialBuilder("oidc.example-provider")  // As registered in Firebase console.
        .setIdToken(idToken)  // ID token from OpenID Connect flow.
        .build();
FirebaseAuth.getInstance()
        .signInWithCredential(credential)
        .addOnSuccessListener(new OnSuccessListener<AuthResult>() {
            @Override
            public void onSuccess(AuthResult authResult) {
                // User is signed in.

                // IdP data available in:
                //    authResult.getAdditionalUserInfo().getProfile()
            }
        })
        .addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                // Handle failure.
            }
        });

次のステップ

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

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

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

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

ユーザーをサインアウトするには、 signOutを呼び出します。

Kotlin+KTX

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();