Google 致力于为黑人社区推动种族平等。查看具体举措

在 Android 上使用 OpenID Connect 进行身份验证

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

如果您已通过 Identity Platform 升级到 Firebase 身份验证,则可以使用您选择的符合 OpenID Connect (OIDC) 标准的提供商通过 Firebase 对您的用户进行身份验证。这使得使用 Firebase 本身不支持的身份提供程序成为可能。

在你开始之前

要使用 OIDC 提供商登录用户,您必须首先从提供商那里收集一些信息:

  • 客户端 ID :标识您的应用程序的提供商唯一的字符串。您的提供商可能会为您支持的每个平台分配不同的客户端 ID。这是您的提供商发布的 ID 令牌中的aud声明的值之一。

  • 客户端密码:提供者用来确认客户端 ID 所有权的密码字符串。对于每个客户端 ID,您都需要一个匹配的客户端密码。 (仅当您使用auth code flow时才需要此值,强烈建议您这样做。)

  • Issuer :标识您的提供者的字符串。此值必须是一个 URL,当附加/.well-known/openid-configuration时,它是提供者的 OIDC 发现文档的位置。例如,如果颁发者是https://auth.example.com ,则发现文档必须在https://auth.example.com/.well-known/openid-configuration可用。

获得上述信息后,启用 OpenID Connect 作为 Firebase 项目的登录提供程序:

  1. 将 Firebase 添加到您的 Android 项目中。

  2. 如果您尚未使用 Identity Platform 升级到 Firebase 身份验证,请执行此操作。 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 提供商以了解他们支持的参数。请注意,您不能使用setCustomParameters()传递 Firebase 所需的参数。这些参数是client_idresponse_typeredirect_uristatescoperesponse_mode

  3. 可选:指定您希望从身份验证提供程序请求的基本配置文件之外的其他 OAuth 2.0 范围。

    Kotlin+KTX

    val scopes = arrayListOf("mail.read", "calendars.read")
    providerBuilder.setScopes(scopes)
    

    Java

    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.getInstance().pendingAuthResult
    if (pendingResultTask != null) {
        // There's something already here! Finish the sign-in for your user.
        pendingResultTask
            .addOnSuccessListener { authResult ->
                // User is signed in.
    
                // IdP data available in
                //   authResult.additionalUserInfo.profile
    
                // The OAuth access token and ID token can also be retrieved:
                val credential = authResult.credential
                if (credential !is OAuthCredential)
                    return@addOnSuccessListener
                val accessToken = credential.accessToken
                val idToken = credential.idToken
            }
            .addOnFailureListener { e ->
                // 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 ID token can also be retrieved:
                  // ((OAuthCredential)authResult.getCredential()).getIdToken().
                }
              })
          .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.getInstance()
        .startActivityForSignInWithProvider(/* activity= */ this, providerBuilder.build())
        .addOnSuccessListener { authResult ->
            // User is signed in.
    
            // IdP data available in:
            //    authResult.additionalUserInfo.profile
    
            // The OAuth access token and ID token can also be retrieved:
            val credential = authResult.credential
            if (credential !is OAuthCredential)
                return@addOnSuccessListener
            val accessToken = credential.accessToken
            val idToken = credential.idToken
        }
        .addOnFailureListener { e ->
            // Handle failure.
        }
    

    Java

    firebaseAuth
        .startActivityForSignInWithProvider(/* activity= */ this, providerBuilder.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:
                // authResult.getCredential().getAccessToken().
                // The OAuth ID token can also be retrieved:
                // authResult.getCredential().getIdToken().
              }
            })
        .addOnFailureListener(
            new OnFailureListener() {
              @Override
              public void onFailure(@NonNull Exception e) {
                // Handle failure.
              }
            });
    
  5. 虽然上述示例侧重于登录流程,但您还可以使用startActivityForLinkWithProvider将 OIDC 提供程序链接到现有用户。例如,您可以将多个提供商链接到同一个用户,允许他们使用其中任何一个登录。

    Kotlin+KTX

    // The user is already signed-in.
    val firebaseUser = FirebaseAuth.getInstance().currentUser
    
    firebaseUser
        ?.startActivityForLinkWithProvider(/* activity= */ this, providerBuilder.build())
        ?.addOnSuccessListener { authResult ->
            // OIDC credential is linked to the current user.
    
            // IdP data available in:
            //   authResult.additionalUserInfo.profile
    
            // The OAuth access token and ID token can also be retrieved:
            val credential = authResult.credential
            if (credential !is OAuthCredential)
                return@addOnSuccessListener
            val accessToken = credential.accessToken
            val idToken = credential.idToken
        }
        ?.addOnFailureListener { e ->
            // 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) {
                // 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 ID token can also be retrieved:
                // authResult.getCredential().getIdToken().
              }
            })
        .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.getInstance().currentUser
    
    firebaseUser
        ?.startActivityForReauthenticateWithProvider(/* activity= */ this, providerBuilder.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 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 { 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 实时数据库和云存储安全规则中,您可以从auth变量中获取登录用户的唯一用户 ID,并使用它来控制用户可以访问哪些数据。

您可以通过将身份验证提供程序凭据链接到现有用户帐户来允许用户使用多个身份验证提供程序登录您的应用程序。

要注销用户,请调用signOut

Java

FirebaseAuth.getInstance().signOut();

Kotlin+KTX

Firebase.auth.signOut()