Azure Active Directory 条件访问功能开发人员指南Developer guidance for the Azure Active Directory Conditional Access feature


本内容适用于较旧版本的 Azure AD v1.0 终结点。This content is for the older Azure AD v1.0 endpoint. 为新项目使用 Microsoft 标识平台Use the Microsoft identity platform for new projects.


有关本文的 Microsoft 标识平台版本,请参阅 Azure Active Directory 条件访问开发人员指南For the Microsoft identity platform version of this article, see Developer guidance for Azure Active Directory Conditional Access.

保护应用安全和保护服务的方法有多种,Azure Active Directory (Azure AD) 中的条件访问功能便是其中之一。The Conditional Access feature in Azure Active Directory (Azure AD) offers one of several ways that you can use to secure your app and protect a service. 通过条件访问功能,可以让开发人员和企业客户以多种方式保护服务的安全,其中包括:Conditional Access enables developers and enterprise customers to protect services in a multitude of ways including:

  • 多重身份验证Multi-factor authentication
  • 仅允许已注册 Intune 的设备访问特定服务Allowing only Intune enrolled devices to access specific services
  • 限制用户位置和 IP 范围Restricting user locations and IP ranges

有关条件访问完整功能的详细信息,请参阅什么是条件访问For more information on the full capabilities of Conditional Access, see What is Conditional Access.

对于生成 Azure AD 应用的开发人员,本文演示了条件访问的使用方法,并介绍了访问应用了条件访问策略且你无法控制的资源将产生的影响。For developers building apps for Azure AD, this article shows how you can use Conditional Access and you'll also learn about the impact of accessing resources that you don't have control over that may have Conditional Access policies applied. 此外,本文还探讨了条件访问对代理流、Web 应用、访问 Microsoft Graph 和调用 API 的影响。The article also explores the implications of Conditional Access in the on-behalf-of flow, web apps, accessing Microsoft Graph, and calling APIs.

本文假定你了解单租户和多租户应用以及常见的身份验证模式Knowledge of single and multi-tenant apps and common authentication patterns is assumed.

条件访问对应用有何影响?How does Conditional Access impact an app?

受影响的应用类型App types impacted

通常,在多数情况下,条件访问不会更改应用的行为或要求开发人员进行任何更改。In most common cases, Conditional Access does not change an app's behavior or requires any changes from the developer.  只有在特定情况下(应用以间接方式或无提示的方式请求服务令牌时),应用才需要进行代码更改以处理条件访问“质询”。Only in certain cases when an app indirectly or silently requests a token for a service, an app requires code changes to handle Conditional Access "challenges".  此过程可能与执行交互式登录请求一样简单。It may be as simple as performing an interactive sign-in request.

具体来说,在以下应用场景下需要代码来处理条件访问“质询”:Specifically, the following scenarios require code to handle Conditional Access "challenges":

  • 执行代理流的应用Apps performing the on-behalf-of flow
  • 访问多个服务/资源的应用Apps accessing multiple services/resources
  • 使用 ADAL.js 的单页应用Single-page apps using ADAL.js
  • 调用资源的 Web 应用Web Apps calling a resource

条件访问策略不仅可应用于应用,还可应用于应用访问的 Web API。Conditional Access policies can be applied to the app, but also can be applied to a web API your app accesses. 要详细了解如何配置条件访问策略,请参阅常用条件访问策略To learn more about how to configure a Conditional Access policy, see Common Conditional Access policies.

根据具体的情况,企业客户随时可以应用和删除条件访问策略。Depending on the scenario, an enterprise customer can apply and remove Conditional Access policies at any time. 应用新策略后,若要使应用继续正常工作,需执行“质询”处理。In order for your app to continue functioning when a new policy is applied, you need to implement the "challenge" handling. 以下示例演示了质询处理的过程。The following examples illustrate challenge handling.

条件访问示例Conditional Access examples

在某些应用场景下,需要进行代码更改来处理条件访问,而在其他应用场景下一切按原样运行。Some scenarios require code changes to handle Conditional Access whereas others work as is. 以下是使用条件访问执行多重身份验证的一些应用场景,可以通过它们深入了解其中的差异。Here are a few scenarios using Conditional Access to do multi-factor authentication that gives some insight into the difference.

  • 你正在构建单租户 iOS 应用,并应用了条件访问策略。You are building a single-tenant iOS app and apply a Conditional Access policy. 应用允许用户登录且不请求访问 API。The app signs in a user and doesn't request access to an API. 用户登录后,自动调用策略,用户需要执行多重身份验证 (MFA)。When the user signs in, the policy is automatically invoked and the user needs to perform multi-factor authentication (MFA).
  • 你正在构建使用中间层服务访问下游 API 的本机应用。You are building a native app that uses a middle tier service to access a downstream API. 公司中使用此应用的企业客户对下游 API 应用了策略。An enterprise customer at the company using this app applies a policy to the downstream API. 最终用户登录时,本机应用将请求访问中间层并将发送令牌。When an end user signs in, the native app requests access to the middle tier and sends the token. 中间层执行代理流来请求访问下游 API。The middle tier performs on-behalf-of flow to request access to the downstream API. 此时,将向中间层发出一个声明“质询”。At this point, a claims "challenge" is presented to the middle tier. 中间层将质询发送回本机应用,本机应用需符合条件访问策略。The middle tier sends the challenge back to the native app, which needs to comply with the Conditional Access policy.

Microsoft GraphMicrosoft Graph

在条件访问环境中构建应用时,需要考虑到 Microsoft Graph 方面的一些特殊注意事项。Microsoft Graph has special considerations when building apps in Conditional Access environments. 通常,条件访问机制的行为相同,但用户看到的策略取决于应用从图形请求的基础数据。Generally, the mechanics of Conditional Access behave the same, but the policies your users see will be based on the underlying data your app is requesting from the graph.

具体而言,所有 Microsoft Graph 范围都表示某个可单独应用策略的数据集。Specifically, all Microsoft Graph scopes represent some dataset that can individually have policies applied. 由于为条件访问策略分配了特定的数据集,因此 Azure AD 会根据 Graph 后面的数据(而非 Graph 本身)强制实施条件访问策略。Since Conditional Access policies are assigned the specific datasets, Azure AD will enforce Conditional Access policies based on the data behind Graph - rather than Graph itself.

例如,如果某个应用请求以下 Microsoft Graph 范围,For example, if an app requests the following Microsoft Graph scopes,

scopes="Bookings.Read.All Mail.Read"

应用可能期望其用户满足针对 Bookings 和 Exchange 设置的所有策略。An app can expect their users to fulfill all policies set on Bookings and Exchange. 某些范围可能会映射到多个数据集(如果授予了访问权限)。Some scopes may map to multiple datasets if it grants access.

符合条件访问策略Complying with a Conditional Access policy

对于多个不同的应用拓扑,会在建立会话时评估条件访问策略。For several different app topologies, a Conditional Access policy is evaluated when the session is established. 条件访问策略在应用和服务的粒度上运行时,调用它的时间很大程度上取决于你尝试完成的应用场景。As a Conditional Access policy operates on the granularity of apps and services, the point at which it is invoked depends heavily on the scenario you're trying to accomplish.

在应用尝试访问具有条件访问策略的服务时,可能会遇到条件访问质询。When your app attempts to access a service with a Conditional Access policy, it may encounter a Conditional Access challenge. 此质询编码在 claims 参数中,而此参数来自 Azure AD 的响应。This challenge is encoded in the claims parameter that comes in a response from Azure AD. 以下是此质询参数的示例:Here's an example of this challenge parameter:


开发人员可以接受此质询并将其追加到新的 Azure AD 请求中。Developers can take this challenge and append it onto a new request to Azure AD. 传递此状态将提示最终用户执行任何必要的操作以符合条件访问策略。Passing this state prompts the end user to perform any action necessary to comply with the Conditional Access policy. 以下应用场景说明了错误的详细信息及如何提取此参数。In the following scenarios, specifics of the error and how to extract the parameter are explained.



Azure AD 条件访问是 Azure AD Premium 包含的一项功能。Azure AD Conditional Access is a feature included in Azure AD Premium. 可以在未授权用户使用情况报表中了解有关许可要求的更多信息。You can learn more about licensing requirements in the unlicensed usage report. 开发人员可以加入 Microsoft 开发人员网络,其中包含企业移动套件(包含 Azure AD Premium)订阅。Developers can join the Microsoft Developer Network, which includes a subscription to the Enterprise Mobility Suite, which includes Azure AD Premium.

特定应用场景的注意事项Considerations for specific scenarios

下列信息仅适用于这些条件访问应用场景:The following information only applies in these Conditional Access scenarios:

  • 执行代理流的应用Apps performing the on-behalf-of flow
  • 访问多个服务/资源的应用Apps accessing multiple services/resources
  • 使用 ADAL.js 的单页应用Single-page apps using ADAL.js

以下各部分讨论更复杂的常见应用场景。The following sections discuss common scenarios that are more complex. 核心运行原则是请求已应用条件访问策略的服务令牌时评估条件访问策略。The core operating principle is Conditional Access policies are evaluated at the time the token is requested for the service that has a Conditional Access policy applied.

方案:执行代理流的应用Scenario: App performing the on-behalf-of flow

在此应用场景中,我们将演示本机应用调用 Web 服务/API 时的场景。In this scenario, we walk through the case in which a native app calls a web service/API. 而此服务将执行“代理”流来调用下游服务。In turn, this service does the "on-behalf-of" flow to call a downstream service. 在本示例中,我们已向下游服务 (Web API 2) 应用条件访问策略,并且使用的是本机应用,而非服务器/守护程序应用。In our case, we've applied our Conditional Access policy to the downstream service (Web API 2) and are using a native app rather than a server/daemon app.


Web API 1 的初始令牌请求未提示最终用户进行多重身份验证,因为 Web API 1 不会始终命中下游 API。The initial token request for Web API 1 does not prompt the end user for multi-factor authentication as Web API 1 may not always hit the downstream API. Web API 1 尝试代表 Web API 2 的用户请求令牌时,请求会失败,因为此用户尚未使用多重身份验证进行登录。Once Web API 1 tries to request a token on-behalf-of the user for Web API 2, the request fails since the user has not signed in with multi-factor authentication.

Azure AD 返回 HTTP 响应,其中包含一些有价值的数据:Azure AD returns an HTTP response with some interesting data:


在此实例中,这些数据是多重身份验证错误说明,但很大一部分的 interaction_required 可能与条件访问有关。In this instance it's a multi-factor authentication error description, but there's a wide range of interaction_required possible pertaining to Conditional Access.

HTTP 400; Bad Request
error_description=AADSTS50076: Due to a configuration change made by your administrator, or because you moved to a new location, you must use multi-factor authentication to access '<Web API 2 App/Client ID>'.

在 Web API 1 中,我们捕获到错误 error=interaction_required,并向桌面应用发送回 claims 质询。In Web API 1, we catch the error error=interaction_required, and send back the claims challenge to the desktop app. 此时,桌面应用可以发出新的 acquireToken() 调用并将 claims 质询追加为额外的查询字符串参数。At that point, the desktop app can make a new acquireToken() call and append the claimschallenge as an extra query string parameter. 这个新请求需要用户执行多重身份验证,然后将此新令牌发送回 Web API 1,并完成代理流。This new request requires the user to do multi-factor authentication and then send this new token back to Web API 1 and complete the on-behalf-of flow.

若要尝试此应用场景,请参阅 .NET 代码示例To try out this scenario, see our .NET code sample. 它演示了如何将声明质询从 Web API 1 传送回本机应用,以及如何在客户端应用内构造新请求。It demonstrates how to pass the claims challenge back from Web API 1 to the native app and construct a new request inside the client app.

方案:访问多个服务的应用Scenario: App accessing multiple services

在此应用场景中,我们将演示 Web 应用访问两个服务且其中之一已分配条件访问策略时的场景。In this scenario, we walk through the case in which a web app accesses two services one of which has a Conditional Access policy assigned. 可能存在应用无需访问两个 Web 服务的方法,具体要取决于应用逻辑。Depending on your app logic, there may exist a path in which your app does not require access to both web services. 在此应用场景中,请求令牌的顺序对最终用户体验有重要影响。In this scenario, the order in which you request a token plays an important role in the end user experience.

假定有 Web 服务 A 和 Web 服务 B,且 Web 服务 B 已应用条件访问策略。Let's assume we have web service A and B and web service B has our Conditional Access policy applied. 虽然初始交互式身份验证请求需要两个服务的许可,但是并非在所有情况都需要条件访问策略。While the initial interactive auth request requires consent for both services, the Conditional Access policy is not required in all cases. 如果应用请求 Web 服务 B 的令牌,则将调用策略,并且对 Web 服务 A 的后续请求也将成功,如下所示。If the app requests a token for web service B, then the policy is invoked and subsequent requests for web service A also succeeds as follows.


或者,如果应用最初请求 Web 服务 A 的令牌,则最终用户将不会调用条件访问策略。Alternatively, if the app initially requests a token for web service A, the end user does not invoke the Conditional Access policy. 这样,应用开发人员就可以控制最终用户体验,且无需在所有情况下强制调用条件访问策略。This allows the app developer to control the end user experience and not force the Conditional Access policy to be invoked in all cases. 最复杂的情况是应用随后请求 Web 服务 B 的令牌。此时,最终用户需要符合条件访问策略。The tricky case is if the app subsequently requests a token for web service B. At this point, the end user needs to comply with the Conditional Access policy. 应用尝试 acquireToken 时,可能会生成以下错误(如下图所示):When the app tries to acquireToken, it may generate the following error (illustrated in the following diagram):

HTTP 400; Bad Request
error_description=AADSTS50076: Due to a configuration change made by your administrator, or because you moved to a new location, you must use multi-factor authentication to access '<Web API App/Client ID>'.


如果应用使用 ADAL 库,将始终以交互方式重新尝试获取令牌并失败。If the app is using the ADAL library, a failure to acquire the token is always retried interactively. 发生此交互式请求时,最终用户有机会符合条件访问策略。When this interactive request occurs, the end user has the opportunity to comply with the Conditional Access. 上述说法是正确的,但当请求是 AcquireTokenSilentAsyncPromptBehavior.Never 时,应用需要执行交互式 AcquireToken 请求来为最终用户提供符合策略的机会。This is true unless the request is a AcquireTokenSilentAsync or PromptBehavior.Never in which case the app needs to perform an interactive AcquireToken request to give the end user the opportunity to comply with the policy.

方案:使用 ADAL.js 的单页应用 (SPA)Scenario: Single-page app (SPA) using ADAL.js

在此应用场景中,我们将演示单页应用 (SPA) 使用 ADAL.js 调用条件访问保护的 Web API 时的场景。In this scenario, we walk through the case when we have a single-page app (SPA), using ADAL.js to call a Conditional Access protected web API. 这是一个简单的体系结构,但围绕条件访问进行开发时需要注意一些细微差异。This is a simple architecture but has some nuances that need to be taken into account when developing around Conditional Access.

在 ADAL.js 中,有多个获取令牌的函数:login()acquireToken(...)acquireTokenPopup(…)acquireTokenRedirect(…)In ADAL.js, there are a few functions that obtain tokens: login(), acquireToken(...), acquireTokenPopup(…), and acquireTokenRedirect(…).

  • login() 通过交互式登录请求获取 ID 令牌,但是无法获取任何服务的访问令牌(包括条件访问保护的 Web API)。login() obtains an ID token through an interactive sign-in request but does not obtain access tokens for any service (including a Conditional Access protected web API).
  • 然后可以使用 acquireToken(…) 以无提示方式获取访问令牌,这意味着在任何情况下它都不会显示 UI。acquireToken(…) can then be used to silently obtain an access token meaning it does not show UI in any circumstance.
  • acquireTokenPopup(…)acquireTokenRedirect(…) 用于以交互方式请求资源的令牌,这意味着它们始终会显示登录 UI。acquireTokenPopup(…) and acquireTokenRedirect(…) are both used to interactively request a token for a resource meaning they always show sign-in UI.

应用需要访问令牌来调用 Web API 时,它尝试 acquireToken(…)When an app needs an access token to call a Web API, it attempts an acquireToken(…). 如果令牌会话过期或我们需要符合条件访问策略时,则 acquireToken 函数失败,应用将使用 acquireTokenPopup()acquireTokenRedirect()If the token session is expired or we need to comply with a Conditional Access policy, then the acquireToken function fails and the app uses acquireTokenPopup() or acquireTokenRedirect().

使用 ADAL 流的单页应用示意图

我们来演示一个使用条件访问应用场景的示例。Let's walk through an example with our Conditional Access scenario. 最终用户刚刚登录站点且未建立会话。The end user just landed on the site and doesn't have a session. 我们执行一个 login() 调用,未通过多重身份验证获取了 ID 令牌。We perform a login() call, get an ID token without multi-factor authentication. 然后用户点击一个按钮,要求应用从 Web API 请求数据。Then the user hits a button that requires the app to request data from a web API. 该应用将尝试执行一个 acquireToken() 调用,但是失败,因为用户尚未执行多重身份验证,且需要符合条件访问策略。The app tries to do an acquireToken() call but fails since the user has not performed multi-factor authentication yet and needs to comply with the Conditional Access policy.

Azure AD 发送回以下 HTTP 响应:Azure AD sends back the following HTTP response:

HTTP 400; Bad Request
error_description=AADSTS50076: Due to a configuration change made by your administrator, or because you moved to a new location, you must use multi-factor authentication to access '<Web API App/Client ID>'.

应用需要捕获 error=interaction_requiredOur app needs to catch the error=interaction_required. 然后应用程序可以在同一个资源上使用 acquireTokenPopup()acquireTokenRedirect()The application can then use either acquireTokenPopup() or acquireTokenRedirect() on the same resource. 用户被强制执行多重身份验证。The user is forced to do a multi-factor authentication. 用户完成多重身份验证后,应用针对所请求资源签发一个新访问令牌。After the user completes the multi-factor authentication, the app is issued a fresh access token for the requested resource.

若要尝试此应用场景,请参阅 JS SPA 代理代码示例To try out this scenario, see our JS SPA On-behalf-of code sample. 此代码示例使用之前通过 JS SPA 注册的条件访问策略和 Web API 演示此应用场景。This code sample uses the Conditional Access policy and web API you registered earlier with a JS SPA to demonstrate this scenario. 它演示了如何正确处理声明质询并获取可用于 Web API 的访问令牌。It shows how to properly handle the claims challenge and get an access token that can be used for your Web API. 或者,请查看常规的 Angular.js 代码示例,获取 Angular SPA 方面的指南。Alternatively, checkout the general Angular.js code sample for guidance on an Angular SPA

另请参阅See also