让用户在 Android 上通过 Apple 登录

本文档介绍如何使用 Identity Platform 将“通过 Apple 登录”添加到 Android 应用。

准备工作

使用 Apple 配置应用

在 Apple Developer 网站上,执行以下操作:

  1. 请按照为网页配置“通过 Apple 登录”中的步骤操作。包括:

    1. 注册返回网址,如下所示:

      https://project-id.firebaseapp.com/__/auth/handler
      
    2. 暂时托管以下网址中的文件以验证您的网域:

      https://project-id.firebaseapp.com/.well-known/apple-developer-domain-association.txt
      

    此外,请记下您的服务 ID 和 Apple 团队 ID,在下一部分中您将需要用到它们。

  2. 使用 Apple 私钥进行登录。 在下一部分中您将需要用到该密钥及其 ID。

  3. 如果您使用 Identity Platform 向用户发送电子邮件,请使用以下电子邮件地址为您的项目配置 Apple 的专用电子邮件中继服务

    noreply@project-id.firebaseapp.com
    

    如果您的应用具有自定义电子邮件模板,您也可以使用自定义电子邮件模板。

符合 Apple 匿名数据要求

Apple 为用户提供了匿名化其数据的选项,包括电子邮件地址。对于选择此选项的用户,Apple 会分配使用 privaterelay.appleid.com 域名进行混淆处理的电子邮件地址。

您的应用必须遵守关于匿名 Apple ID 的所有适用的 Apple 开发者政策或条款。这包括在将任何个人身份信息 (PII) 与匿名 Apple ID 关联之前征得用户同意。涉及 PII 的操作包括但不限于:

  • 将电子邮件地址关联至匿名 Apple ID,或者将匿名 Apple ID 关联至电子邮件地址。
  • 将电话号码关联至匿名 Apple ID,或者将匿名 Apple ID 关联至电话号码。
  • 将非匿名社交凭据(Facebook 账号、Google 账号等)关联至匿名 Apple ID,或者将匿名 Apple ID 关联至非匿名社交凭据。

如需了解详情,请参阅您的 Apple 开发者账号的《Apple 开发者计划许可协议》。

将 Apple 配置为提供商

要将 Apple 配置为身份提供商,请执行以下操作:

  1. 前往 Google Cloud 控制台中的身份提供方页面。

    转到“身份提供商”页面

  2. 点击添加提供商

  3. 从列表中选择 Apple

  4. 平台下,选择 Android

  5. 输入您的服务 IDApple 团队 ID密钥 ID私钥

  6. 点击已获授权的网域下的添加网域,以注册您应用的网域。出于开发目的,localhost 默认处于启用状态。

  7. 配置您的应用下,点击 Android。将代码段复制到应用的代码中,以初始化 Identity Platform Client SDK。

  8. 点击保存

让用户通过 Client SDK 登录

  1. 使用 ID apple.com 创建 OAuthProvider 提供商对象的实例:

    Java

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

    Kotlin

    val provider = OAuthProvider.newBuilder("apple.com")
    
  2. 可选:添加 OAuth 范围。范围指定您要从 Apple 请求哪些数据。更敏感的数据可能需要特定范围。默认情况下,启用每个电子邮件地址一个账号后,Identity Platform 会申请 emailname 范围。

    Java

    List<String> scopes =
        new ArrayList<String>() {
          {
            add("email");
            add("name");
          }
        };
    provider.setScopes(scopes);
    

    Kotlin

    provider.setScopes(arrayOf("email", "name"))
    
  3. 可选:对身份验证流程进行本地化。您可以指定语言,也可以使用设备的默认语言:

    Java

    // Localize the Apple authentication screen in French.
    provider.addCustomParameter("locale", "fr");
    

    Kotlin

    // Localize the Apple authentication screen in French.
    provider.addCustomParameter("locale", "fr");
    
  4. 用户通过 Identity Platform 登录。

    1. 通过调用 startActivityForSignInWithProvider() 检查响应是否已存在:

      Java

      mAuth = FirebaseAuth.getInstance();
      Task<AuthResult> pending = mAuth.getPendingAuthResult();
      if (pending != null) {
          pending.addOnSuccessListener(new OnSuccessListener<AuthResult>() {
              @Override
              public void onSuccess(AuthResult authResult) {
                  Log.d(TAG, "checkPending:onSuccess:" + authResult);
                  // Get the user profile with authResult.getUser() and
                  // authResult.getAdditionalUserInfo(), and the ID
                  // token from Apple with authResult.getCredential().
              }
          }).addOnFailureListener(new OnFailureListener() {
              @Override
              public void onFailure(@NonNull Exception e) {
                  Log.w(TAG, "checkPending:onFailure", e);
              }
          });
      } else {
          Log.d(TAG, "pending: null");
      }
      

      Kotlin

      val pending = auth.pendingAuthResult
      if (pending != null) {
          pending.addOnSuccessListener { authResult ->
              Log.d(TAG, "checkPending:onSuccess:$authResult")
              // Get the user profile with authResult.getUser() and
              // authResult.getAdditionalUserInfo(), and the ID
              // token from Apple with authResult.getCredential().
          }.addOnFailureListener { e ->
              Log.w(TAG, "checkPending:onFailure", e)
          }
      } else {
          Log.d(TAG, "pending: null")
      }
      

      登录会将您的 Activity 置于后台,这意味着系统可以在身份验证流程中将其回收。检查结果是否已存在可避免用户登录两次。

    2. 如果不存在待处理的结果,请调用 startActivityForSignInWithProvider()

      Java

      mAuth.startActivityForSignInWithProvider(this, provider.build())
          .addOnSuccessListener(
                  new OnSuccessListener<AuthResult>() {
                      @Override
                      public void onSuccess(AuthResult authResult) {
                          // Sign-in successful!
                          Log.d(TAG, "activitySignIn:onSuccess:" + authResult.getUser());
                          FirebaseUser user = authResult.getUser();
                          // ...
                      }
                  })
          .addOnFailureListener(
                  new OnFailureListener() {
                      @Override
                      public void onFailure(@NonNull Exception e) {
                          Log.w(TAG, "activitySignIn:onFailure", e);
                      }
                  });
      

      Kotlin

      auth.startActivityForSignInWithProvider(this, provider.build())
        .addOnSuccessListener { authResult ->
            // Sign-in successful!
            Log.d(TAG, "activitySignIn:onSuccess:${authResult.user}")
            val user = authResult.user
            // ...
        }
        .addOnFailureListener { e ->
            Log.w(TAG, "activitySignIn:onFailure", e)
        }
      

与许多其他身份提供商不同,Apple 不提供照片网址。

如果用户选择不与应用分享其真实电子邮件,Apple 会为该用户预配唯一的电子邮件地址来与应用共享。此电子邮件的格式为 xyz@privaterelay.appleid.com。如果您配置了私人电子邮件中继服务,则 Apple 会将发送到匿名地址的电子邮件转发到用户的真实电子邮件地址。

Apple 只会在用户首次登录时与应用共享用户信息(例如显示名)。在大多数情况下,Identity Platform 会存储此数据,以便您可以在未来的会话中使用 firebase.auth().currentUser.displayName 提取该数据。但是,如果您允许用户在与 Identity Platform 集成之前通过 Apple 登录您的应用,则无法获得用户信息。

后续步骤