将应用服务或 Azure Functions 应用配置为使用 Apple 登录提供程序(预览版)进行身份验证。

本文介绍如何配置 Azure 应用服务或 Azure Functions,以便将 Apple 登录用作身份验证提供程序。

若要完成本文中的过程,必须注册 Apple 开发人员计划。 若要注册 Apple 开发人员计划,请转到 developer.apple.com/programs/enroll。

谨慎

启用 Apple 登录功能会在某些客户端(如 Azure 门户、Azure CLI 和 Azure PowerShell)上禁用应用程序的应用服务身份验证和授权功能的管理。 此功能依赖于新的 API 接口,在预览期间尚未纳入所有管理体验中。

在 Apple 开发人员门户中创建应用程序

在 Apple 开发人员门户中创建应用 ID 和服务 ID。

  1. 在 Apple 开发人员门户上,依次转到“证书”、“标识符”和“配置文件”。

  2. 在“标识符”选项卡上,选择 (+) 按钮 。

  3. 在“注册新的标识符”页上选择“应用 ID”,然后选择“继续” 。 应用 ID 包括一个或多个服务 ID。

    屏幕截图显示 Apple 开发人员门户中的“注册新标识符”页,其中突出显示了应用 ID。

  4. 在 “注册应用 ID ”页上,提供说明和捆绑 ID。

  5. 从功能列表中,选择“ 使用 Apple 登录 ”,然后选择“ 继续”。 记下此步骤中的应用 ID 前缀(团队 ID )。 稍后需要用到它。

    屏幕截图显示了在 Apple 开发人员门户中配置新的应用标识符。

  6. 查看应用注册信息,并选择“注册”。

  7. 同样,在“标识符”选项卡上,选择 (+) 按钮 。

    屏幕截图显示了“标识符”页,其中突出显示了 Apple 开发人员门户中的加号图标。

  8. 在“注册新的标识符”页上选择“服务 ID”,然后选择“继续” 。

    屏幕截图显示 Apple 开发人员门户中的“注册新标识符”页,其中突出显示了“服务 ID”。

  9. 在“注册服务 ID”页上,提供说明和标识符。 然后选择“配置”。

    屏幕截图中包含描述和标识符。

    说明是用户在同意屏幕上看到的内容。 标识符是你的客户端 ID,用于在应用服务中配置 Apple 提供商。

  10. 在对话框中,将主要应用 ID 设置为之前创建的应用 ID。 在域部分中指定应用程序的域。 对于返回 URL,可以使用 URL <app-url>/.auth/login/apple/callback。 例如,https://contoso.chinacloudsites.cn/.auth/login/apple/callback。 然后选择“添加”和“保存” 。

    屏幕截图显示了为注册指定域和返回 URL。

  11. 查看服务注册信息,然后选择“ 保存”。

生成客户端密码

Apple 要求应用开发人员创建 JSON Web 令牌并将其签名为客户端机密值。 若要生成此密码,首先从 Apple 开发人员门户生成椭圆曲线私钥并将其下载。 然后使用该密钥对具有特定有效负载的 JWT 进行签名。

创建和下载私钥

  1. 在 Apple 开发人员门户的“密钥”选项卡上,选择“创建密钥”或选择 (+) 按钮 。
  2. 在 “注册新密钥 ”页上,为密钥指定名称,选择 “使用 Apple 登录”,然后选择“ 配置”。
  3. 在“配置密钥”页上,将密钥链接到之前创建的主应用 ID,然后选择“保存” 。
  4. 通过确认信息并选择 “继续”完成创建密钥。 然后查看信息并选择“ 注册”。
  5. 在“下载密钥”页上,下载密钥。 它下载为 .p8 (PKCS#8) 文件。 使用文件内容对客户端密钥 JWT 进行签名。

构建客户端密码 JWT

Apple 要求客户端密码是 JWT 的 base64 编码。 解码的 JWT 应具有类似于以下示例的结构的有效负载:

{
  "alg": "ES256",
  "kid": "URKEYID001",
}.{
  "sub": "com.yourcompany.app1",
  "nbf": 1560203207,
  "exp": 1560289607,
  "iss": "ABC123DEFG",
  "aud": "https://appleid.apple.com"
}.[Signature]
  • sub:Apple 客户端标识,同时也是服务标识
  • iss:你的 Apple 开发人员团队 ID
  • aud:Apple 正在接收令牌,因此他们是受众
  • exp:在 nbf 后不超过 6 个月

此有效负载的 base64 编码版本如下所示:

eyJhbGciOiJFUzI1NiIsImtpZCI6IlVSS0VZSUQwMDEifQ.eyJzdWIiOiJjb20ueW91cmNvbXBhbnkuYXBwMSIsIm5iZiI6MTU2MDIwMzIwNywiZXhwIjoxNTYwMjg5NjA3LCJpc3MiOiJBQkMxMjNERUZHIiwiYXVkIjoiaHR0cHM6Ly9hcHBsZWlkLmFwcGxlLmNvbSJ9.ABSXELWuTbgqfrIUz7bLi6nXvkXAz5O8vt0jB2dSHTQTib1x1DSP4__4UrlKI-pdzNg1sgeocolPNTmDKazO8-BHAZCsdeeTNlgFEzBytIpMKFfVEQbEtGRkam5IeclUK7S9oOva4EK4jV4VmgDrr-LGWWO3TaAxAvy3_ZoKohvFFkVG

注释

Apple 不接受客户端机密 JWT,其到期日超出创建日期或 nbf 日期六个月以上。 至少每六个月轮换一次客户端密码。

对客户端密码 JWT 进行签名

使用.p8文件对客户端密钥 JWT 进行签名,该文件是您之前下载的。 此文件是一个 PCKS#8 文件,其中包含 PEM 格式的私钥。 可使用许多库来创建 JWT 并对其进行签名。

联机提供了不同类型的开源库,可用于创建和签名 JWT。 有关生成 JWT 的详细信息,请参阅 JSON Web 令牌(JWT)。

例如,生成客户端密码的一种方法是导入 Microsoft.IdentityModel.Tokens NuGet 包 并运行如下所示的 C# 代码:

using Microsoft.IdentityModel.Tokens;

public static string GetAppleClientSecret(string teamId, string clientId, string keyId, string p8key)
{
    string audience = "https://appleid.apple.com";

    string issuer = teamId;
    string subject = clientId;
    string kid = keyId;

    IList<Claim> claims = new List<Claim> {
        new Claim ("sub", subject)
    };

    CngKey cngKey = CngKey.Import(Convert.FromBase64String(p8key), CngKeyBlobFormat.Pkcs8PrivateBlob);

    SigningCredentials signingCred = new SigningCredentials(
        new ECDsaSecurityKey(new ECDsaCng(cngKey)),
        SecurityAlgorithms.EcdsaSha256
    );

    JwtSecurityToken token = new JwtSecurityToken(
        issuer,
        audience,
        claims,
        DateTime.Now,
        DateTime.Now.AddDays(180),
        signingCred
    );
    token.Header.Add("kid", kid);
    token.Header.Remove("typ");

    JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();

    return tokenHandler.WriteToken(token);
}
  • teamId:你的 Apple 开发人员团队 ID
  • clientId:Apple 客户端 ID,也是服务 ID
  • p8key:PEM 格式键。 可以通过在文本编辑器中打开 .p8 文件,并复制 -----BEGIN PRIVATE KEY----- 和 -----END PRIVATE KEY----- 之间的所有内容(不包含换行符)来获取密钥。
  • keyId:下载的密钥的 ID

返回的该令牌是用于配置 Apple 提供程序的客户端密钥值。

重要

客户端密码是一个非常重要的安全凭据。 不要与任何人共享此机密,也不会将其分发到客户端应用程序中。

使用你选择的设置名称将客户端机密添加为应用的应用程序设置。 记下此名称备用。

向应用程序添加提供程序信息

注释

所需的配置采用新的 API 格式,目前仅受基于文件的配置(预览版)支持。 需要按照此处的步骤使用此类文件。

本部分介绍如何更新配置以包含新的 IDP。 后面提供了配置示例。

  1. 在identityProviders对象中,如果尚不存在apple对象,添加apple对象。

  2. 向该密钥分配一个对象,在其中包含 registration 对象,还可以包含 login 对象:

    "apple" : {
       "registration" : {
            "clientId": "<client ID>",
            "clientSecretSettingName": "APP_SETTING_CONTAINING_APPLE_CLIENT_SECRET" 
        },
       "login": {
             "scopes": []
       }
    }
    
  3. 在 registration 对象中,将 clientId 设置为您收集到的客户端 ID。

  4. 在 registration 对象中,将 clientSecretSettingName 设置为存储客户端机密的应用程序设置名称。

  5. 在对象中login,可以选择设置scopes数组以包含使用 Apple 进行身份验证时使用的作用域列表,例如名称和电子邮件。 如果配置了权限范围,当用户首次登录时,同意屏幕会显式请求这些权限范围。

设置此配置后,即可在应用中使用 Apple 提供程序进行身份验证。

完整的配置可能类似于以下示例,其中APPLE_GENERATED_CLIENT_SECRET设置指向包含生成的 JWT 的应用程序设置:

{
    "platform": {
        "enabled": true
    },
    "globalValidation": {
        "redirectToProvider": "apple",
        "unauthenticatedClientAction": "RedirectToLoginPage"
    },
    "identityProviders": {
        "apple": {
            "registration": {
                "clientId": "com.contoso.example.client",
                "clientSecretSettingName": "APPLE_GENERATED_CLIENT_SECRET"
            },
            "login": {
                "scopes": []
            }
        }
    },
    "login": {
        "tokenStore": {
            "enabled": true
        }
    }     
}