在 Azure AD B2C 中配置资源所有者密码凭据流Configure the resource owner password credentials flow in Azure AD B2C

资源所有者密码凭据 (ROPC) 流是 OAuth 标准身份验证流,其中应用程序(也称为信赖方)使用有效凭据(例如用户 ID 和密码)交换 ID 令牌、访问令牌和刷新令牌。The resource owner password credentials (ROPC) flow is an OAuth standard authentication flow where the application, also known as the relying party, exchanges valid credentials such as userid and password for an ID token, access token, and a refresh token.

备注

此功能目前以公共预览版提供。This feature is in public preview.

ROPC 流说明ROPC flow notes

在 Azure Active Directory B2C (Azure AD B2C) 中支持以下选项:In Azure Active Directory B2C (Azure AD B2C), the following options are supported:

  • 本机客户端:当代码在用户端设备上运行时,将在身份验证期间进行用户交互。Native Client: User interaction during authentication happens when code runs on a user-side device. 设备可以是在本机操作系统(如 Android 和 iOS)中运行的移动应用程序。The device can be a mobile application that's running in a native operating system, such as Android and iOS.
  • 公共客户端流:只有通过应用程序收集的用户凭据才会在 API 调用中发送。Public client flow: Only user credentials, gathered by an application, are sent in the API call. 不会发送应用程序的凭据。The credentials of the application are not sent.
  • 添加新声明:可更改 ID 令牌内容以添加新的声明。Add new claims: The ID token contents can be changed to add new claims.

不支持以下流:The following flows are not supported:

  • 服务器到服务器:标识保护系统在交互过程中需要从调用方(本地客户端)收集的可靠 IP 地址。Server-to-server: The identity protection system needs a reliable IP address gathered from the caller (the native client) as part of the interaction. 在服务器端 API 调用中,仅使用服务器的 IP 地址。In a server-side API call, only the server's IP address is used. 如果超过了失败身份验证的动态阈值,则标识保护系统可能将重复的 IP 地址识别为攻击者。If a dynamic threshold of failed authentications is exceeded, the identity protection system may identify a repeated IP address as an attacker.
  • 机密客户端流:应用程序客户端 ID 已验证,但应用程序机密未验证。Confidential client flow: The application client ID is validated, but the application secret is not validated.

使用 ROPC 流时,请考虑下列事项:When using the ROPC flow, consider the following:

  • 当需要用户交互的身份验证流发生中断时,ROPC 将不起作用。ROPC doesn't work when there is any interruption to the authentication flow that needs user interaction. 例如,当密码过期或需要更改时、需要多重身份验证时,或者在登录期间需要收集更多信息(例如,用户许可)时。For example, when a password has expired or needs to be changed, multi-factor authentication is required, or when more information needs to be collected during sign-in (for example, user consent).
  • ROPC 仅支持本地帐户。ROPC supports local accounts only. 用户无法通过联合标识提供者登录。Users can't sign in with federated identity providers.
  • 会话管理(包括“使我保持登录”(KMSI))不适用。Session Management, including keep me signed-in (KMSI), is not applicable.

创建资源所有者用户流Create a resource owner user flow

  1. 以 Azure AD B2C 租户的全局管理员身份登录 Azure 门户。Sign in to the Azure portal as the global administrator of your Azure AD B2C tenant.
  2. 若要切换到 Azure AD B2C 租户,请在门户右上角选择 B2C 目录。To switch to your Azure AD B2C tenant, select the B2C directory in the upper-right corner of the portal.
  3. 选择“用户流”,然后选择“新建用户流”。Select User flows, and select New user flow.
  4. 选择“使用资源所有者密码凭据(ROPC)登录”。Select Sign in using resource owner password credentials (ROPC).
  5. 在“版本”下,确保选中“预览版”,然后选择“创建”。 Under Version, make sure Preview is selected, and then select Create.
  6. 提供用户流名称,例如 ROPC_Auth。Provide a name for the user flow, such as ROPC_Auth.
  7. 在“应用程序声明”下,单击“显示更多”。Under Application claims, click Show more.
  8. 选择应用程序所需的应用程序声明,例如“显示名称”、“电子邮件”和“标识提供者”。Select the application claims that you need for your application, such as Display Name, Email Address, and Identity Provider.
  9. 选择“确定”,然后选择“创建” 。Select OK, and then select Create.
  10. 单击“运行用户流”。Click Run user flow.

你随后会看到一个终结点,如以下示例所示:You'll then see an endpoint such as this example:

https://<tenant-name>.b2clogin.cn/<tenant-name>.partner.onmschina.cn/B2C_1_ROPC_Auth/v2.0/.well-known/openid-configuration

注册应用程序Register an application

要在 Azure AD B2C 租户中注册应用程序,可以使用新的统一“应用注册”体验或旧版“应用程序(旧版)”体验 。To register an application in your Azure AD B2C tenant, you can use our new unified App registrations experience or our legacy Applications (Legacy) experience. 详细了解此新体验Learn more about the new experience.

  1. 登录 Azure 门户Sign in to the Azure portal.
  2. 在顶部菜单中选择“目录 + 订阅”筛选器,然后选择包含Azure AD B2C 租户的目录。Select the Directory + subscription filter in the top menu, and then select the directory that contains your Azure AD B2C tenant.
  3. 在左侧菜单中,选择“Azure AD B2C”。In the left menu, select Azure AD B2C. 或者,选择“所有服务”并搜索并选择“Azure AD B2C”。Or, select All services and search for and select Azure AD B2C.
  4. 选择“应用注册”,然后选择“新建注册” 。Select App registrations, and then select New registration.
  5. 输入应用程序的“名称”。Enter a Name for the application. 例如,ROPC_Auth_app。For example, ROPC_Auth_app.
  6. 保留其他值不变,然后选择“注册”。Leave the other values as they are, and then select Register.
  7. 记录“应用程序(客户端) ID”,以便在后续步骤中使用。Record the Application (client) ID for use in a later step.
  8. 在“管理”下,选择“身份验证”。 Under Manage, select Authentication.
  9. 选择“尝试新体验”(如果已显示)。Select Try out the new experience (if shown).
  10. 在“默认客户端类型”下,选择“是”,将应用程序视为公共客户端。Under Default client type, select Yes to treat the application as a public client. ROPC 流需要此设置。This setting is required for the ROPC flow.
  11. 选择“保存”。Select Save.
  12. 在左侧菜单中,选择“清单”以打开清单编辑器。In the left menu, select Manifest to open the manifest editor.
  13. 将“oauth2AllowImplicitFlow”属性设置为“true”:Set the oauth2AllowImplicitFlow attribute to true:
    "oauth2AllowImplicitFlow": true,
    
  14. 选择“保存”。Select Save.

测试用户流Test the user flow

使用最喜欢的 API 开发应用程序来生成 API 调用,然后查看响应以调试用户流。Use your favorite API development application to generate an API call, and review the response to debug your user flow. 使用下表中的信息构建如下所示的调用作为 POST 请求的正文:Construct a call like this with the information in the following table as the body of the POST request:

  • 将 <tenant-name>.partner.onmschina.cn 替换为 B2C 租户的名称。Replace <tenant-name>.partner.onmschina.cn with the name of your B2C tenant.
  • 将<B2C_1A_ROPC_Auth> 替换为资源所有者密码凭据策略的全名。Replace <B2C_1A_ROPC_Auth> with the full name of your resource owner password credentials policy.
  • 将 <bef2222d56-552f-4a5b-b90a-1988a7d634c3> 替换为注册中的应用程序 ID。Replace <bef2222d56-552f-4a5b-b90a-1988a7d634c3> with the Application ID from your registration.

https://<tenant-name>.b2clogin.cn/<tenant-name>.partner.onmschina.cn/B2C_1_ROPC_Auth/oauth2/v2.0/token

Key Value
usernameusername leadiocl@outlook.com
passwordpassword Passxword1Passxword1
grant_typegrant_type passwordpassword
scopescope openid <bef2222d56-552f-4a5b-b90a-1988a7d634c3> offline_accessopenid <bef2222d56-552f-4a5b-b90a-1988a7d634c3> offline_access
client_idclient_id <bef2222d56-552f-4a5b-b90a-1988a7d634c3>
response_typeresponse_type token id_tokentoken id_token

Client_id 是之前记录为应用程序 ID 的值。Client_id is the value that you previously noted as the application ID. 如果想要接收刷新令牌,则 Offline_access 是可选的。Offline_access is optional if you want to receive a refresh token. 使用的用户名和密码必须是来自 Azure AD B2C 租户中现有用户的凭据。The username and password that you use must be credentials from an existing user in your Azure AD B2C tenant.

实际的 POST 请求如下所示:The actual POST request looks like the following:

POST /<tenant-name>.partner.onmschina.cn/B2C_1_ROPC_Auth/oauth2/v2.0/token HTTP/1.1
Host: <tenant-name>.b2clogin.cn
Content-Type: application/x-www-form-urlencoded

username=leadiocl%40trashmail.ws&password=Passxword1&grant_type=password&scope=openid+bef22d56-552f-4a5b-b90a-1988a7d634ce+offline_access&client_id=bef22d56-552f-4a5b-b90a-1988a7d634ce&response_type=token+id_token

脱机访问的成功响应如以下示例所示:A successful response with offline-access looks like the following example:

{
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ik9YQjNhdTNScWhUQWN6R0RWZDM5djNpTmlyTWhqN2wxMjIySnh6TmgwRlkifQ.eyJpc3MiOiJodHRwczovL3RlLmNwaW0ud2luZG93cy5uZXQvZjA2YzJmZTgtNzA5Zi00MDMwLTg1ZGMtMzhhNGJmZDllODJkL3YyLjAvIiwiZXhwIjoxNTEzMTMwMDc4LCJuYmYiOjE1MTMxMjY0NzgsImF1ZCI6ImJlZjIyZDU2LTU1MmYtNGE1Yi1iOTBhLTE5ODhhN2Q2MzRjZSIsIm9pZCI6IjNjM2I5NjljLThjNDktNGUxMS1hNGVmLWZkYjJmMzkyZjA0OSIsInN1YiI6Ik5vdCBzdXBwb3J0ZWQgY3VycmVudGx5LiBVc2Ugb2lkIGNsYWltLiIsImF6cCI6ImJlZjIyZDU2LTU1MmYtNGE1Yi1iOTBhLTE5ODhhN2Q2MzRjZSIsInZlciI6IjEuMCIsImlhdCI6MTUxMzEyNjQ3OH0.MSEThYZxCS4SevBw3-3ecnVLUkucFkehH-gH-P7SFcJ-MhsBeQEpMF1Rzu_R9kUqV3qEWKAPYCNdZ3_P4Dd3a63iG6m9TnO1Vt5SKTETuhVx3Xl5LYeA1i3Slt9Y7LIicn59hGKRZ8ddrQzkqj69j723ooy01amrXvF6zNOudh0acseszt7fbzzofyagKPerxaeTH0NgyOinLwXu0eNj_6RtF9gBfgwVidRy9OzXUJnqm1GdrS61XUqiIUtv4H04jYxDem7ek6E4jsH809uSXT0iD5_4C5bDHrpO1N6pXSasmVR9GM1XgfXA_IRLFU4Nd26CzGl1NjbhLnvli2qY4A",
    "token_type": "Bearer",
    "expires_in": "3600",
    "refresh_token": "eyJraWQiOiJacW9pQlp2TW5pYVc2MUY0TnlfR3REVk1EVFBLbUJLb0FUcWQ1ZWFja1hBIiwidmVyIjoiMS4wIiwiemlwIjoiRGVmbGF0ZSIsInNlciI6IjEuMCJ9.aJ_2UW14dh4saWTQ0jLJ7ByQs5JzIeW_AU9Q_RVFgrrnYiPhikEc68ilvWWo8B20KTRB_s7oy_Eoh5LACsqU6Oz0Mjnh0-DxgrMblUOTAQ9dbfAT5WoLZiCBJIz4YT5OUA_RAGjhBUkqGwdWEumDExQnXIjRSeaUBmWCQHPPguV1_5wSj8aW2zIzYIMbofvpjwIATlbIZwJ7ufnLypRuq_MDbZhJkegDw10KI4MHJlJ40Ip8mCOe0XeJIDpfefiJ6WQpUq4zl06NO7j8kvDoVq9WALJIao7LYk_x9UIT-3d0W0eDBHGSRcNgtMYpymaN9ltx6djcEesXNn4CFnWG3g.y6KKeA9EcsW9zW-g.TrTSgn4WBt18gezegxihBla9SLSTC3YfDROQsL9K4yX4400FKlTlf-2l9CnpGTEdWXVi7sIMHCl8S4oUiXd-rvY2mn_NfDrbbVJfgKp1j7Nnq9FFyeJEFcP_FtUXgsNTG9iwfzWox04B1d845qNRWiS9N8BhAAAIdz5N0ChHuOxsVOC0Y_Ly3DNe-JQyXcq964M6-jp3cgi4UqMxT837L6pLY5Ih_iPsSfyHzstsFeqyUIktnzt1MpTlyW-_GDyFK1S-SyV8PPQ7phgFouw2jho1iboHX70RlDGYyVmP1CfQzKE_zWxj3rgaCZvYMWN8fUenoiatzhvWkUM7dhqKGjofPeL8rOMkhl6afLLjObzhUg3PZFcMR6guLjQdEwQFufWxGjfpvaHycZSKeWu6-7dF8Hy_nyMLLdBpUkdrXPob_5gRiaH72KvncSIFvJLqhY3NgXO05Fy87PORjggXwYkhWh4FgQZBIYD6h0CSk2nfFjR9uD9EKiBBWSBZj814S_Jdw6HESFtn91thpvU3hi3qNOi1m41gg1vt5Kh35A5AyDY1J7a9i_lN4B7e_pknXlVX6Z-Z2BYZvwAU7KLKsy5a99p9FX0lg6QweDzhukXrB4wgfKvVRTo.mjk92wMk-zUSrzuuuXPVeg",
    "id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ik9YQjNhdTNScWhUQWN6R0RWZDM5djNpTmlyTWhqN2wxMjIySnh6TmgwRlkifQ.eyJleHAiOjE1MTMxMzAwNzgsIm5iZiI6MTUxMzEyNjQ3OCwidmVyIjoiMS4wIiwiaXNzIjoiaHR0cHM6Ly90ZS5jcGltLndpbmRvd3MubmV0L2YwNmMyZmU4LTcwOWYtNDAzMC04NWRjLTM4YTRiZmQ5ZTgyZC92Mi4wLyIsInN1YiI6Ik5vdCBzdXBwb3J0ZWQgY3VycmVudGx5LiBVc2Ugb2lkIGNsYWltLiIsImF1ZCI6ImJlZjIyZDU2LTU1MmYtNGE1Yi1iOTBhLTE5ODhhN2Q2MzRjZSIsImFjciI6ImIyY18xYV9yZXNvdXJjZW93bmVydjIiLCJpYXQiOjE1MTMxMjY0NzgsImF1dGhfdGltZSI6MTUxMzEyNjQ3OCwib2lkIjoiM2MzYjk2OWMtOGM0OS00ZTExLWE0ZWYtZmRiMmYzOTJmMDQ5IiwiYXRfaGFzaCI6Ikd6QUNCTVJtcklwYm9OdkFtNHhMWEEifQ.iAJg13cgySsdH3cmoEPGZB_g-4O8KWvGr6W5VzRXtkrlLoKB1pl4hL6f_0xOrxnQwj2sUgW-wjsCVzMc_dkHSwd9QFZ4EYJEJbi1LMGk2lW-PgjsbwHPDU1mz-SR1PeqqJgvOqrzXo0YHXr-e07M4v4Tko-i_OYcrdJzj4Bkv7ZZilsSj62lNig4HkxTIWi5Ec2gD79bPKzgCtIww1KRnwmrlnCOrMFYNj-0T3lTDcXAQog63MOacf7OuRVUC5k_IdseigeMSscrYrNrH28s3r0JoqDhNUTewuw1jx0X6gdqQWZKOLJ7OF_EJMP-BkRTixBGK5eW2YeUUEVQxsFlUg"
}

兑换刷新令牌Redeem a refresh token

使用下表中的信息构造如此处所示的 POST 调用作为请求的正文:Construct a POST call like the one shown here with the information in the following table as the body of the request:

https://<tenant-name>.b2clogin.cn/<tenant-name>.partner.onmschina.cn/B2C_1_ROPC_Auth/oauth2/v2.0/token

密钥Key Value
grant_typegrant_type refresh_tokenrefresh_token
response_typeresponse_type id_tokenid_token
client_idclient_id <bef2222d56-552f-4a5b-b90a-1988a7d634c3>
resourceresource <bef2222d56-552f-4a5b-b90a-1988a7d634c3>
refresh_tokenrefresh_token eyJraWQiOiJacW9pQlp2TW5pYVc2MUY0TnlfR3...eyJraWQiOiJacW9pQlp2TW5pYVc2MUY0TnlfR3...

Client_idresource 是之前记录为应用程序 ID 的值。Client_id and resource are the values that you previously noted as the application ID. Refresh_token 是在前述身份验证调用中收到的令牌。Refresh_token is the token that you received in the authentication call mentioned previously.

成功响应如以下示例所示:A successful response looks like the following example:

{
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1jNTdkTzZRR1RWQndhTmsifQ.eyJpc3MiOiJodHRwczovL2xvZ2luLm1pY3Jvc29mdG9ubGluZS5jb20vNTE2ZmMwNjUtZmYzNi00YjkzLWFhNWEtZDZlZWRhN2NiYWM4L3YyLjAvIiwiZXhwIjoxNTMzNjc2NTkwLCJuYmYiOjE1MzM2NzI5OTAsImF1ZCI6IjljNTA2MThjLWY5NTEtNDlhNS1iZmU1LWQ3ODA4NTEyMWMzYSIsImlkcCI6IkxvY2FsQWNjb3VudCIsInN1YiI6ImJmZDgwODBjLTBjNDAtNDNjYS05ZTI3LTUyZTAyNzIyNWYyMSIsIm5hbWUiOiJEYXZpZE11IiwiZW1haWxzIjpbImRhdmlkd20xMDMwQGhvdG1haWwuY29tIl0sInRmcCI6IkIyQ18xX1JPUENfQXV0aCIsImF6cCI6IjljNTA2MThjLWY5NTEtNDlhNS1iZmU1LWQ3ODA4NTEyMWMzYSIsInZlciI6IjEuMCIsImlhdCI6MTUzMzY3Mjk5MH0.RULWeBR8--s5cCGG6XOi8m-AGyCaASx9W5B3tNUQjbVkHnGdo2_OUrnVoOZ1PTcrc1b0PQM2kVWi7NpYn57ifnqL_feTJPDbj9FJ8BmyxULdoECWxSM6KHsOPWZOIg5y1lNwN_IQ2HNF6UaDyYf1ZIM-jHr-uSfUnQXyWRnGDwNKX7TQbFmFk4oFMbPxTE7ioWAmxSnroiiB4__P9D0rUM1vf_qfzemf2ErIWSF9rGtCNBG-BvJlr3ZMCxIhRiIWNM2bVY0i3Nprzj0V8_FM6q8U19bvg9yDEzUcbe_1PMqzP3IrXW9N1XvQHupsOj8Keb7SmpgY1GG091X6wBCypw",
    "id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1jNTdkTzZRR1RWQndhTmsifQ.eyJleHAiOjE1MzM2NzY1OTAsIm5iZiI6MTUzMzY3Mjk5MCwidmVyIjoiMS4wIiwiaXNzIjoiaHR0cHM6Ly9sb2dpbi5taWNyb3NvZnRvbmxpbmUuY29tLzUxNmZjMDY1LWZmMzYtNGI5My1hYTVhLWQ2ZWVkYTdjYmFjOC92Mi4wLyIsInN1YiI6ImJmZDgwODBjLTBjNDAtNDNjYS05ZTI3LTUyZTAyNzIyNWYyMSIsImF1ZCI6IjljNTA2MThjLWY5NTEtNDlhNS1iZmU1LWQ3ODA4NTEyMWMzYSIsImlhdCI6MTUzMzY3Mjk5MCwiYXV0aF90aW1lIjoxNTMzNjcyOTkwLCJpZHAiOiJMb2NhbEFjY291bnQiLCJuYW1lIjoiRGF2aWRNdSIsImVtYWlscyI6WyJkYXZpZHdtMTAzMEBob3RtYWlsLmNvbSJdLCJ0ZnAiOiJCMkNfMV9ST1BDX0F1dGgiLCJhdF9oYXNoIjoiYW5hZ3QtX1NveUtBQV9UNFBLaHN4dyJ9.bPzpUFh94XFHXC_yR6qH_Unf6_hN-9-BjDXOzrdb1AuoU6-owQ3fWDxNBUbYEPALid3sgm4qhJ6BROFKryD8aWfrNyaErnYZwZ6rliHk4foa3JsbDgM3yNGPL0hzOFpC4Y9QhUjNgQOxvnQLtqbHVNonSvBc7VVPAjBDza44GowmvLORfJ1qkTjdrFM75HlLVeQch8cUNf-Ova77JdG5WHgYgqRhAq1OhV68YgEpQkARyz77zbAz9zZEHZZlgsli8UV6C-CPcmoHbwS-85mLzF9nLxhzjgIXJwckB6I7lvTpfuRtaqZIb3pMYeHZJaxaNLDvq9Qe4N-danXABg1B2w",
    "token_type": "Bearer",
    "not_before": 1533672990,
    "expires_in": 3600,
    "expires_on": 1533676590,
    "resource": "bef2222d56-552f-4a5b-b90a-1988a7d634c3",
    "id_token_expires_in": 3600,
    "profile_info": "eyJ2ZXIiOiIxLjAiLCJ0aWQiOiI1MTZmYzA2NS1mZjM2LTRiOTMtYWE1YS1kNmVlZGE3Y2JhYzgiLCJzdWIiOm51bGwsIm5hbWUiOiJEYXZpZE11IiwicHJlZmVycmVkX3VzZXJuYW1lIjpudWxsLCJpZHAiOiJMb2NhbEFjY291bnQifQ",
    "refresh_token": "eyJraWQiOiJjcGltY29yZV8wOTI1MjAxNSIsInZlciI6IjEuMCIsInppcCI6IkRlZmxhdGUiLCJzZXIiOiIxLjAifQ..8oC4Q6aKdr35yMWm.p43lns-cfWNFbtmrhvtssQXCItb3E9aSLafZJ6nKnnpXGQ-ZapOOyH7hPK7AN_RT7NMsQwNdy0Fyv_hOMrFbMPZNvHSa91RsQIvBZ73-CVy0HNF0grSezjCATg4NVHfricuQVegEmZKFOoNP6TaMC2kIlEi3rhrrO8VE3ZFQ3Jjo6j91BJaE9ybb02HWOoKqlzHiazwQyUHujw_R0TyXaQCI_gtLARr5QUXm7hlAfHhxR9uewQKlRbeuMH8nCMLSMASCJyzfeSJTjXmA0F0VrXozrqzOJdyy0EETPR7oA48MJ9l6C2sy2ZELkqpOM3xhbhV-Re7nM09b8DeWuCw7VNTcQc9DKnIHDR-H5U2Tc-lMJQadgUNZv7KGSRGTyprWb7wF7FEPnRNID5PCDV_N_yoQpI7VvJO_NotXEgHFo7OHs5Gsgwpl5mrDtymYzIMM7onTflOlu46em_qltji7xcWNOuHq4AeOlcY9ZythZgJH7livljReTwyX8QuUwpomXVEUGDc5pAnvgSozxnUbM7AlwfUeJZRT45P7L7683RSqChdNxiQk0sXUECqxnFxMAz4VUzld2yFe-pzvxFF4_feQjBEmSCAvekpvJUrEticEs4QzByV5UZ2ZCKccijFTg4doACiCo_z13JTm47mxm-5jUhXOQqiL69oxztk.KqI-z2LlC77lvwqmeFtdGQ",
    "refresh_token_expires_in": 1209600
}

备注

通过图形 API 创建用户时,应用程序需要具有 Microsoft Graph 的“openid”、“offline_access”和“profile”权限。When creating users via Graph API, the application needs to have "openid", "offline_access", and "profile" permissions from Microsoft Graph.

使用首选本机 SDK 实现或使用 AppAuthImplement with your preferred native SDK or use App-Auth

Azure AD B2C 实现符合公共客户端资源所有者密码凭据的 OAuth 2.0 标准,并且应与大多数客户端 SDK 兼容。The Azure AD B2C implementation meets OAuth 2.0 standards for public client resource owner password credentials and should be compatible with most client SDKs. 我们已在生产环境中针对适用于 iOS 的 AppAuth 和适用于 Android 的 AppAuth 广泛测试这一流程。We have tested this flow extensively, in production, with AppAuth for iOS and AppAuth for Android. 有关最新信息,请参阅适用于 OAuth 2.0 的本机应用 SDK 和实现新式最佳做法的 OpenID ConnectFor the latest information, see Native App SDK for OAuth 2.0 and OpenID Connect implementing modern best practices.

从 GitHub 下载已配置为与 Azure AD B2C 一起使用的工作示例:用于 Android用于 iOSDownload working samples that have been configured for use with Azure AD B2C from GitHub, for Android and for iOS.