让用户通过 Apple 账户登录

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

准备工作

使用 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 控制台中的 Identity Providers(身份提供商)页面。

    转到“身份提供商”页面

  2. 点击添加提供商

  3. 从列表中选择 Apple

  4. 平台下,选择 Web

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

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

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

  8. 点击保存

让用户通过 Client SDK 登录

要让用户登录,请执行以下操作:

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

    Web 版本 9

    import { OAuthProvider } from "firebase/auth";
    
    const provider = new OAuthProvider('apple.com');

    Web 版本 8

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

    Web 版本 9

    provider.addScope('email');
    provider.addScope('name');

    Web 版本 8

    provider.addScope('email');
    provider.addScope('name');
  3. 可选:对身份验证流程进行本地化。您可以指定语言,也可以使用设备的默认语言。如需了解受支持的语言区域,请参阅“通过 Apple 登录”文档

    Web 版本 9

    provider.setCustomParameters({
      // Localize the Apple authentication screen in French.
      locale: 'fr'
    });

    Web 版本 8

    provider.setCustomParameters({
      // Localize the Apple authentication screen in French.
      locale: 'fr'
    });
  4. 使用提供商对象让用户登录。您可以打开一个弹出式窗口,也可以重定向当前网页。对于移动设备用户而言,重定向更为便捷。

    如需显示弹出式窗口,请调用 signInWithPopup()

    Web 版本 9

    import { getAuth, signInWithPopup, OAuthProvider } from "firebase/auth";
    
    const auth = getAuth();
    signInWithPopup(auth, provider)
      .then((result) => {
        // The signed-in user info.
        const user = result.user;
    
        // Apple credential
        const credential = OAuthProvider.credentialFromResult(result);
        const accessToken = credential.accessToken;
        const idToken = credential.idToken;
    
        // IdP data available using getAdditionalUserInfo(result)
        // ...
      })
      .catch((error) => {
        // Handle Errors here.
        const errorCode = error.code;
        const errorMessage = error.message;
        // The email of the user's account used.
        const email = error.customData.email;
        // The credential that was used.
        const credential = OAuthProvider.credentialFromError(error);
    
        // ...
      });

    Web 版本 8

    firebase
      .auth()
      .signInWithPopup(provider)
      .then((result) => {
        /** @type {firebase.auth.OAuthCredential} */
        var credential = result.credential;
    
        // The signed-in user info.
        var user = result.user;
    
        // You can also get the Apple OAuth Access and ID Tokens.
        var accessToken = credential.accessToken;
        var idToken = credential.idToken;
    
        // IdP data available using getAdditionalUserInfo(result)
      // ...
      })
      .catch((error) => {
        // Handle Errors here.
        var errorCode = error.code;
        var errorMessage = error.message;
        // The email of the user's account used.
        var email = error.email;
        // The firebase.auth.AuthCredential type that was used.
        var credential = error.credential;
    
        // ...
      });

    如需重定向页面,请先调用 signInWithRedirect()

    使用 signInWithRedirectlinkWithRedirectreauthenticateWithRedirect 时,请遵循最佳实践

    Web 版本 9

    import { getAuth, signInWithRedirect } from "firebase/auth";
    
    const auth = getAuth();
    signInWithRedirect(auth, provider);

    Web 版本 8

    firebase.auth().signInWithRedirect(provider);

    然后,在网页加载时调用 getRedirectResult() 来检索 Apple 令牌:

    Web 版本 9

    import { getAuth, getRedirectResult, OAuthProvider } from "firebase/auth";
    
    // Result from Redirect auth flow.
    const auth = getAuth();
    getRedirectResult(auth)
      .then((result) => {
        const credential = OAuthProvider.credentialFromResult(result);
        if (credential) {
          // You can also get the Apple OAuth Access and ID Tokens.
          const accessToken = credential.accessToken;
          const idToken = credential.idToken;
        }
        // The signed-in user info.
        const user = result.user;
      })
      .catch((error) => {
        // Handle Errors here.
        const errorCode = error.code;
        const errorMessage = error.message;
        // The email of the user's account used.
        const email = error.customData.email;
        // The credential that was used.
        const credential = OAuthProvider.credentialFromError(error);
    
        // ...
      });

    Web 版本 8

    // Result from Redirect auth flow.
    firebase
      .auth()
      .getRedirectResult()
      .then((result) => {
        if (result.credential) {
          /** @type {firebase.auth.OAuthCredential} */
          var credential = result.credential;
    
          // You can get the Apple OAuth Access and ID Tokens.
          var accessToken = credential.accessToken;
          var idToken = credential.idToken;
    
          // IdP data available in result.additionalUserInfo.profile.
          // ...
        }
        // The signed-in user info.
        var user = result.user;
      })
      .catch((error) => {
        // Handle Errors here.
        var errorCode = error.code;
        var errorMessage = error.message;
        // The email of the user's account used.
        var email = error.email;
        // The firebase.auth.AuthCredential type that was used.
        var credential = error.credential;
    
        // ...
      });

    您还可以在此处捕获并处理错误。如需查看错误代码列表,请参阅 API 参考文档

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

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

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

后续步骤