Microsoft 标识平台和隐式授权流Microsoft identity platform and Implicit grant flow

使用 Microsoft 标识平台终结点,可以让拥有 Microsoft 工作或学校帐户的用户登录到单页应用。With the Microsoft identity platform endpoint, you can sign users into your single-page apps with work or school accounts from Microsoft. 主要在浏览器上运行的单页面和其他 JavaScript 应用程序在身份验证时面临一些有趣的挑战:Single-page and other JavaScript apps that run primarily in a browser face a few interesting challenges when it comes to authentication:

  • 这些应用的安全特征与传统的基于服务器的 Web 应用程序大不相同。The security characteristics of these apps are significantly different from traditional server-based web applications.
  • 许多授权服务器与标识提供者不支持 CORS 请求。Many authorization servers and identity providers do not support CORS requests.
  • 重定向离开应用程序的完整网页浏览器变得对用户经验特别有侵略性。Full page browser redirects away from the app become particularly invasive to the user experience.

对于这些应用程序(Angular、Ember.js、React.js 等),Microsoft 标识平台支持 OAuth 2.0 隐式授权流。For these applications (Angular, Ember.js, React.js, and so on), Microsoft identity platform supports the OAuth 2.0 Implicit Grant flow. 有关隐式流的说明,请参阅 OAuth 2.0 规范The implicit flow is described in the OAuth 2.0 Specification. 其主要优点是它可让应用程序从 Microsoft 标识平台获取令牌,无需要执行后端服务器凭据交换。Its primary benefit is that it allows the app to get tokens from Microsoft identity platform without performing a backend server credential exchange. 这可让应用登录用户、维护会话,并获取客户端 JavaScript 代码中所有其他 Web API 的令牌。This allows the app to sign in the user, maintain session, and get tokens to other web APIs all within the client JavaScript code. 使用隐式流时有几个重要的安全注意事项,具体而言,是关于客户端用户模拟的注意事项。There are a few important security considerations to take into account when using the implicit flow specifically around client and user impersonation.

本文介绍如何在应用程序中直接针对协议进行编程。This article describes how to program directly against the protocol in your application. 如果可能,建议你改用受支持的 Microsoft 身份验证库 (MSAL) 来获取令牌并调用受保护的 Web APIWhen possible, we recommend you use the supported Microsoft Authentication Libraries (MSAL) instead to acquire tokens and call secured web APIs. 另请参阅使用 MSAL 的示例应用Also take a look at the sample apps that use MSAL.

但是,如果不想在单页面应用中使用库,而是要自行发送协议消息,请遵循下面的常规步骤。However, if you prefer not to use a library in your single-page app and send protocol messages yourself, follow the general steps below.

OAuth2 隐式授权的适用方案Suitable scenarios for the OAuth2 implicit grant

OAuth2 规范声明,设计隐式授权是为了实现用户代理应用程序,即在浏览器中执行的 JavaScript 应用程序。The OAuth2 specification declares that the implicit grant has been devised to enable user-agent applications - that is to say, JavaScript applications executing within a browser. 此类应用程序的最典型特征是,JavaScript 代码用于访问服务器资源(通常是 Web API)以及相应地更新应用程序用户体验。The defining characteristic of such applications is that JavaScript code is used for accessing server resources (typically a web API) and for updating the application user experience accordingly. 以 Gmail 或 Outlook Web Access 之类的应用程序为例:在收件箱中选择某封邮件时,只有邮件可视化面板会更改以显示新的选择内容,页面的其余部分保持不变。Think of applications like Gmail or Outlook Web Access: when you select a message from your inbox, only the message visualization panel changes to display the new selection, while the rest of the page remains unmodified. 此特征明显不同于传统的基于重定向的 Web 应用,在后者中,每个用户交互都会造成整页回发,并造成整页呈现新的服务器响应。This characteristic is in contrast with traditional redirect-based Web apps, where every user interaction results in a full page postback and a full page rendering of the new server response.

将基于 JavaScript 的方法发挥到极致的应用程序称为单页应用程序或 SPA。Applications that take the JavaScript based approach to its extreme are called single-page applications, or SPAs. 其思想是,这些应用程序仅提供初始 HTML 页和关联的 JavaScript,所有后续交互都由通过 JavaScript 执行的 Web API 调用驱动。The idea is that these applications only serve an initial HTML page and associated JavaScript, with all subsequent interactions being driven by web API calls performed via JavaScript. 但是,应用程序大多是由回传驱动,但偶尔执行 JS 调用的混合方法也并非罕见;关于隐式流用法的介绍也与这些方法有关。However, hybrid approaches, where the application is mostly postback-driven but performs occasional JS calls, are not uncommon - the discussion about implicit flow usage is relevant for those as well.

基于重定向的应用程序通常通过 Cookie 确保请求的安全性,但该方法不适用于 JavaScript 应用程序。Redirect-based applications typically secure their requests via cookies, however, that approach does not work as well for JavaScript applications. Cookie 仅适用于生成 Cookie 时所针对的域,而 JavaScript 调用可能会定向到其他域。Cookies only work against the domain they have been generated for, while JavaScript calls might be directed toward other domains. 事实上,情况往往是这样的:以调用 Microsoft 图形 API、Office API、Azure API 的应用程序为例 – 这些应用程序全都位于提供应用程序的域之外。In fact, that will frequently be the case: think of applications invoking Microsoft Graph API, Office API, Azure API - all residing outside the domain from where the application is served. JavaScript 应用程序的发展趋势是完全没有后端,全部依赖第三方 Web API 来实现其业务功能。A growing trend for JavaScript applications is to have no backend at all, relying 100% on third party web APIs to implement their business function.

当前情况下,若要保护对 Web API 的调用,首选方法是使用 OAuth2 持有者令牌方法,其中每个调用都带有一个 OAuth2 访问令牌。Currently, the preferred method of protecting calls to a web API is to use the OAuth2 bearer token approach, where every call is accompanied by an OAuth2 access token. Web API 会检查传入的访问令牌,如果在其中找到所需的范围,则会向请求操作授予访问权限。The web API examines the incoming access token and, if it finds in it the necessary scopes, it grants access to the requested operation. 隐式流提供了方便的机制供 JavaScript 应用程序获取 Web API 的访问令牌,并提供了很多与 Cookie 相关的优点:The implicit flow provides a convenient mechanism for JavaScript applications to obtain access tokens for a web API, offering numerous advantages in respect to cookies:

  • 可以可靠地获取令牌而无需跨源调用 – 强制注册令牌要返回到的重定向 URI 可保证令牌不会转到其他位置Tokens can be reliably obtained without any need for cross origin calls - mandatory registration of the redirect URI to which tokens are return guarantees that tokens are not displaced
  • JavaScript 应用程序可以针对任意数目的目标 Web API 获取所需数目的访问令牌 - 对域没有限制JavaScript applications can obtain as many access tokens as they need, for as many web APIs they target - with no restriction on domains
  • 会话或本地存储等 HTML5 功能可授予令牌缓存和生存期管理的完全控制权,但是 Cookie 管理对于应用而言是不透明的HTML5 features like session or local storage grant full control over token caching and lifetime management, whereas cookies management is opaque to the app
  • 访问令牌不容易遭受跨站点请求伪造 (CSRF) 攻击Access tokens aren't susceptible to Cross-site request forgery (CSRF) attacks

隐式授权流不颁发刷新令牌,这主要是出于安全考虑。The implicit grant flow does not issue refresh tokens, mostly for security reasons. 刷新令牌的范围不像访问令牌那么窄,前者授予更大的权力,因此万一泄露,会造成更大的损害。在隐式流中,令牌在 URL 中传递,因此遭到拦截的风险高于授权代码授予。A refresh token isn't as narrowly scoped as access tokens, granting far more power hence inflicting far more damage in case it is leaked out. In the implicit flow, tokens are delivered in the URL, hence the risk of interception is higher than in the authorization code grant.

不过,JavaScript 应用程序提供另一种可任其处置的机制,可用于续订访问令牌,且不会重复提示用户输入凭据。However, a JavaScript application has another mechanism at its disposal for renewing access tokens without repeatedly prompting the user for credentials. 应用程序可以使用隐藏的 iframe 来针对 Azure AD 的授权终结点执行新的令牌请求:只要浏览器仍然针对 Azure AD 域提供活动会话(读取:有会话 Cookie),则身份验证请求就可以成功且不需要用户交互。The application can use a hidden iframe to perform new token requests against the authorization endpoint of Azure AD: as long as the browser still has an active session (read: has a session cookie) against the Azure AD domain, the authentication request can successfully occur without any need for user interaction.

此模型授予 JavaScript 应用程序相关功能,以允许其独立续订访问令牌,甚至允许其为新的 API 获取新的访问令牌,前提是用户此前已表示同意。This model grants the JavaScript application the ability to independently renew access tokens and even acquire new ones for a new API (provided that the user previously consented for them). 这样可以避免因获取、维护和保护高价值项目(例如刷新令牌)而增加的负担。This avoids the added burden of acquiring, maintaining, and protecting a high value artifact such as a refresh token. 实现无提示续订的项目(Azure AD 会话 Cookie)在应用程序外部进行管理。The artifact that makes the silent renewal possible, the Azure AD session cookie, is managed outside of the application. 此方法的另一优势是,用户可以通过登录到 Azure AD 的任意应用程序从 Azure AD(在任意浏览器标签页中运行)注销。Another advantage of this approach is a user can sign out from Azure AD, using any of the applications signed into Azure AD, running in any of the browser tabs. 这样会删除 Azure AD 会话 Cookie,而 JavaScript 应用程序会自动失去为已注销用户续订令牌的功能。This results in the deletion of the Azure AD session cookie, and the JavaScript application will automatically lose the ability to renew tokens for the signed out user.

隐式授权适合我的应用吗?Is the implicit grant suitable for my app?

与其他授权相比,隐式授权具有更多风险,需要注意的方面已有详细记录(例如,在隐式流中误用访问令牌来模拟资源所有者OAuth 2.0 威胁模型和安全注意事项)。The implicit grant presents more risks than other grants, and the areas you need to pay attention to are well documented (for example, Misuse of Access Token to Impersonate Resource Owner in Implicit Flow and OAuth 2.0 Threat Model and Security Considerations). 但是,风险走势之所以较高,主要是因为它要启用执行活动代码的应用程序,并由远程资源提供给浏览器。However, the higher risk profile is largely due to the fact that it is meant to enable applications that execute active code, served by a remote resource to a browser. 如果要规划一个 SPA 体系结构,则不要设置后端组件或尝试通过 JavaScript 调用 Web API,而应使用隐式流来获取令牌。If you are planning an SPA architecture, have no backend components or intend to invoke a web API via JavaScript, use of the implicit flow for token acquisition is recommended.

如果应用程序是本机客户端,则隐式流并不太适合。If your application is a native client, the implicit flow isn't a great fit. 在使用本机客户端的情况下,如果没有 Azure AD 会话 Cookie,应用程序无法长时间维持一个会话。The absence of the Azure AD session cookie in the context of a native client deprives your application from the means of maintaining a long lived session. 这意味着,在为新资源获取访问令牌时,应用程序会反复提示用户。Which means your application will repeatedly prompt the user when obtaining access tokens for new resources.

如果要开发包含后端的 Web 应用程序,并需要从其后端代码使用 API,则也不适合使用隐式流。If you are developing a Web application that includes a backend, and consuming an API from its backend code, the implicit flow is also not a good fit. 其他授权可以提供更强大的功能。Other grants give you far more power. 例如,授予 OAuth2 客户端凭据即可获取的令牌能够反映分配给应用程序本身的权限,这不同于用户委派。For example, the OAuth2 client credentials grant provides the ability to obtain tokens that reflect the permissions assigned to the application itself, as opposed to user delegations. 这意味着,即使在用户未积极参与某个会话这样的情况下,客户端也可始终对资源进行程序性的访问。This means the client has the ability to maintain programmatic access to resources even when a user is not actively engaged in a session, and so on. 不仅如此,此类授权还提供更严格的安全保证。Not only that, but such grants give higher security guarantees. 例如,访问令牌从不通过用户浏览器传输,因此不会有被保存在浏览器历史记录中的风险,等等。For instance, access tokens never transit through the user browser, they don't risk being saved in the browser history, and so on. 在请求令牌时,客户端应用程序还可以进行严格的身份验证。The client application can also perform strong authentication when requesting a token.

协议图Protocol diagram

下图显示了整个隐式登录流的样子,后续各部分更详细地介绍了每个步骤。The following diagram shows what the entire implicit sign-in flow looks like and the sections that follow describe each step in more detail.

显示隐式登录流的关系图

发送登录请求Send the sign-in request

最初将用户登录到应用时,可以发送 OpenID Connect 身份验证请求,并从 Microsoft 标识平台终结点获取 id_tokenTo initially sign the user into your app, you can send an OpenID Connect authentication request and get an id_token from the Microsoft identity platform endpoint.

重要

若要成功请求 ID 令牌和/或访问令牌,必须通过在“隐式授权”部分下选择“ID 令牌”和/或“访问令牌”,为 Azure 门户 - 应用注册页中的应用注册启用相应的隐式授权流。 To successfully request an ID token and/or an access token, the app registration in the Azure portal - App registrations page must have the corresponding implicit grant flow enabled, by selecting ID tokens and.or access tokens under the Implicit grant section. 如果未启用,将返回 unsupported_response 错误:为输入参数“response_type”提供的值不允许用于此客户端。预期值为“code””If it's not enabled, an unsupported_response error will be returned: The provided value for the input parameter 'response_type' is not allowed for this client. Expected value is 'code'

// Line breaks for legibility only

https://login.partner.microsoftonline.cn/{tenant}/oauth2/v2.0/authorize?
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&response_type=id_token
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&scope=openid
&response_mode=fragment
&state=12345
&nonce=678910

提示

若要使用隐式流测试登录,请单击 https://login.partner.microsoftonline.cn/common/oauth2/v2.0/authorize..在登录之后,浏览器应重定向到 https://localhost/myapp/ ,并且地址栏中有一个 id_tokenTo test signing in using the implicit flow, click https://login.partner.microsoftonline.cn/common/oauth2/v2.0/authorize... After signing in, your browser should be redirected to https://localhost/myapp/ with an id_token in the address bar.

参数Parameter 类型Type 说明Description
tenant 必填required 请求路径中的 {tenant} 值可用于控制哪些用户可以登录应用程序。The {tenant} value in the path of the request can be used to control who can sign into the application. 可以使用的值包括 commonorganizationsconsumers 和租户标识符。The allowed values are common, organizations, consumers, and tenant identifiers. 有关详细信息,请参阅协议基础知识For more detail, see protocol basics.
client_id 必填required Azure 门户 - 应用注册页分配给应用的应用程序(客户端)ID。The Application (client) ID that the Azure portal - App registrations page assigned to your app.
response_type 必填required 必须包含 OpenID Connect 登录的 id_tokenMust include id_token for OpenID Connect sign-in. 也可以包含 response_type tokenIt may also include the response_type token. 此处使用 token ,让应用能够立即从授权终结点接收访问令牌,而无需向授权终结点发出第二次请求。Using token here will allow your app to receive an access token immediately from the authorize endpoint without having to make a second request to the authorize endpoint. 如果使用 token response_type,scope 参数必须包含范围,以指出要对哪个资源(例如,Microsoft Graph 上的 user.read)发出令牌。If you use the token response_type, the scope parameter must contain a scope indicating which resource to issue the token for (for example, user.read on Microsoft Graph).
redirect_uri 建议recommended 应用的 redirect_uri,应用可向其发送及从其接收身份验证响应。The redirect_uri of your app, where authentication responses can be sent and received by your app. 它必须完全符合在门户中注册的其中一个 redirect_uris,否则必须是编码的 url。It must exactly match one of the redirect_uris you registered in the portal, except it must be url encoded.
scope 必填required 范围的空格分隔列表。A space-separated list of scopes. 对于 OpenID Connect (id_token),它必须包含范围 openid,该范围在许可 UI 中会转换为“将你登录”权限。For OpenID Connect (id_tokens), it must include the scope openid, which translates to the "Sign you in" permission in the consent UI. 或者,也可以包含 emailprofile 范围,以获取对其他用户数据的访问权限。Optionally you may also want to include the email and profile scopes for gaining access to additional user data. 也可以在此请求中包含其他范围,以请求对各种资源的许可(如果请求了访问令牌)。You may also include other scopes in this request for requesting consent to various resources, if an access token is requested.
response_mode 可选optional 指定将生成的令牌送回到应用程序时应该使用的方法。Specifies the method that should be used to send the resulting token back to your app. 默认为仅查询访问令牌,但如果请求包括 id_token,则会进行分段。Defaults to query for just an access token, but fragment if the request includes an id_token.
state 建议recommended 同样随令牌响应返回的请求中所包含的值。A value included in the request that will also be returned in the token response. 可以是想要的任何内容的字符串。It can be a string of any content that you wish. 随机生成的唯一值通常用于 防止跨站点请求伪造攻击A randomly generated unique value is typically used for preventing cross-site request forgery attacks. 该 state 也用于在身份验证请求出现之前,于应用中编码用户的状态信息,例如之前所在的网页或视图。The state is also used to encode information about the user's state in the app before the authentication request occurred, such as the page or view they were on.
nonce 必填required 由应用程序生成且包含在请求中的值,以声明方式包含在生成的 id_token 中。A value included in the request, generated by the app, that will be included in the resulting id_token as a claim. 应用程序接着便可确认此值,以减少令牌重新执行攻击。The app can then verify this value to mitigate token replay attacks. 此值通常是随机的唯一字符串,可用以识别请求的来源。The value is typically a randomized, unique string that can be used to identify the origin of the request. 只有请求 id_token 时才是必需的。Only required when an id_token is requested.
prompt 可选optional 表示需要的用户交互类型。Indicates the type of user interaction that is required. 目前的有效值为“login”、“none”、“select_account”和“consent”。The only valid values at this time are 'login', 'none', 'select_account', and 'consent'. prompt=login 将强制用户在该请求上输入凭据,取消单一登录。prompt=login will force the user to enter their credentials on that request, negating single-sign on. prompt=none 则相反 - 它确保不对用户显示任何交互式提示。prompt=none is the opposite - it will ensure that the user isn't presented with any interactive prompt whatsoever. 如果请求无法通过单一登录静默完成,则 Microsoft 标识平台终结点将返回一个错误。If the request can't be completed silently via single-sign on, the Microsoft identity platform endpoint will return an error. prompt=select_account 将用户发送到一个帐户选取器,其中将显示在会话中记住的所有帐户。prompt=select_account sends the user to an account picker where all of the accounts remembered in the session will appear. prompt=consent 会在用户登录之后触发 OAuth 同意对话框,要求用户向应用授予权限。prompt=consent will trigger the OAuth consent dialog after the user signs in, asking the user to grant permissions to the app.
login_hint 可选optional 如果事先知道其用户名称,可用于预先填充用户登录页面的用户名称/电子邮件地址字段。Can be used to pre-fill the username/email address field of the sign in page for the user, if you know their username ahead of time. 通常,应用会在重新身份验证期间使用此参数,并且已经使用 preferred_username 声明从前次登录提取用户名。Often apps will use this parameter during re-authentication, having already extracted the username from a previous sign-in using the preferred_username claim.
domain_hint 可选optional 如果包含,它跳过用户在登录页上经历的基于电子邮件的发现过程,导致稍微更加流畅的用户体验。If included, it will skip the email-based discovery process that user goes through on the sign in page, leading to a slightly more streamlined user experience. 这通常用于在单个租户中运行的业务线应用,它们会提供给定租户中的域名。This is commonly used for Line of Business apps that operate in a single tenant, where they will provide a domain name within a given tenant. 这样就会将用户转发到该租户的联合身份验证提供程序。This will forward the user to the federation provider for that tenant. 请注意,这会阻止来宾登录到此应用程序。Note that this will prevent guests from signing into this application.

此时,将请求用户输入凭据并完成身份验证。At this point, the user will be asked to enter their credentials and complete the authentication. Microsoft 标识平台终结点还会确保用户已许可 scope 查询参数中指定的权限。The Microsoft identity platform endpoint will also ensure that the user has consented to the permissions indicated in the scope query parameter. 如果用户未曾同意这些权限的任何一项,就请求用户同意请求的权限。If the user has consented to none of those permissions, it will ask the user to consent to the required permissions. 有关详细信息,请参阅权限、同意和多租户应用For more info, see permissions, consent, and multi-tenant apps.

用户经过身份验证并授予许可后,Microsoft 标识平台终结点将使用 response_mode 参数中指定的方法,将响应返回到位于所指示的 redirect_uri 的应用。Once the user authenticates and grants consent, the Microsoft identity platform endpoint will return a response to your app at the indicated redirect_uri, using the method specified in the response_mode parameter.

成功的响应Successful response

使用 response_mode=fragmentresponse_type=id_token+token 的成功响应如下所示(为方便阅读,包含了换行符):A successful response using response_mode=fragment and response_type=id_token+token looks like the following (with line breaks for legibility):

GET https://localhost/myapp/#
&token_type=Bearer
&expires_in=3599
&id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...
&state=12345
参数Parameter 说明Description
access_token 如果 response_type 包含 token,则包含该参数。Included if response_type includes token. 应用请求的访问令牌。The access token that the app requested. 访问令牌不得进行解码或检查,应当作为不透明字符串对待。The access token shouldn't be decoded or otherwise inspected, it should be treated as an opaque string.
token_type 如果 response_type 包含 token,则包含该参数。Included if response_type includes token. 始终为 BearerWill always be Bearer.
expires_in 如果 response_type 包含 token,则包含该参数。Included if response_type includes token. 表示令牌有效的秒数(针对缓存目的)。Indicates the number of seconds the token is valid, for caching purposes.
scope 如果 response_type 包含 token,则包含该参数。Included if response_type includes token. 表示 access_token 的有效范围。Indicates the scope(s) for which the access_token will be valid. 可能不包括所有请求的范围(如果它们不适用于用户)。May not include all of the scopes requested, if they were not applicable to the user.
id_token 有符号 JSON Web 令牌 (JWT)。A signed JSON Web Token (JWT). 应用可以解码此令牌的段,以请求已登录用户的相关信息。The app can decode the segments of this token to request information about the user who signed in. 应用可以缓存并显示值,但不应依赖于这些值来获取任何授权或安全边界。The app can cache the values and display them, but it shouldn't rely on them for any authorization or security boundaries. 有关 id_tokens 的详细信息,请参阅 id_token referenceFor more information about id_tokens, see the id_token reference.
注意: 仅当已请求 openid 作用域时提供。Note: Only provided if openid scope was requested.
state 如果请求中包含 state 参数,响应中就应该出现相同的值。If a state parameter is included in the request, the same value should appear in the response. 应用应该验证请求和响应中的 state 值是否完全相同。The app should verify that the state values in the request and response are identical.

错误响应Error response

错误响应可能也发送到 redirect_uri ,让应用可以适当地处理:Error responses may also be sent to the redirect_uri so the app can handle them appropriately:

GET https://localhost/myapp/#
error=access_denied
&error_description=the+user+canceled+the+authentication
参数Parameter 说明Description
error 可用于分类发生的错误类型与响应错误的错误码字符串。An error code string that can be used to classify types of errors that occur, and can be used to react to errors.
error_description 帮助开发人员识别身份验证错误根本原因的特定错误消息。A specific error message that can help a developer identify the root cause of an authentication error.

在后台以无提示方式获取访问令牌Getting access tokens silently in the background

已经将用户登录到单页应用,现在可以通过无提示方式获取访问令牌以调用受到 Microsoft 标识平台保护的 Web API,例如 Microsoft GraphNow that you've signed the user into your single-page app, you can silently get access tokens for calling web APIs secured by Microsoft identity platform, such as the Microsoft Graph. 即使已使用 token response_type 收到令牌,仍然可以使用此方法获取其他资源的令牌,而无需再次将用户重定向到登录页。Even if you already received a token using the token response_type, you can use this method to acquire tokens to additional resources without having to redirect the user to sign in again.

在正常的 OpenID Connect/OAuth 流中,可以通过对 Microsoft 标识平台 /token 终结点进行请求来实现此目的。In the normal OpenID Connect/OAuth flow, you would do this by making a request to the Microsoft identity platform /token endpoint. 但是,Microsoft 标识平台终结点不支持 CORS 请求,因此进行 AJAX 调用以获取和刷新令牌是不可能的。However, the Microsoft identity platform endpoint does not support CORS requests, so making AJAX calls to get and refresh tokens is out of the question. 相反,可以在隐藏的 iframe 中使用隐式流,以获取其他 Web API 的新令牌:Instead, you can use the implicit flow in a hidden iframe to get new tokens for other web APIs:

// Line breaks for legibility only

https://login.partner.microsoftonline.cn/{tenant}/oauth2/v2.0/authorize?
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&response_type=token
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&scope=https%3A%2F%2Fmicrosoftgraph.chinacloudapi.cn%2Fuser.read
&response_mode=fragment
&state=12345
&nonce=678910
&prompt=none
&login_hint=myuser@mycompany.com

有关 URL 中的查询参数的详细信息,请参阅发送登录请求For details on the query parameters in the URL, see send the sign in request.

提示

请尝试将以下请求复制并粘贴到浏览器选项卡中!Try copy & pasting the below request into a browser tab! (不要忘记使用适用于用户的正确值替换 login_hint 值)(Don't forget to replace the login_hint values with the correct value for your user)

https://login.partner.microsoftonline.cn/common/oauth2/v2.0/authorize?client_id=6731de76-14a6-49ae-97bc-6eba6914391e&response_type=token&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F&scope=https%3A%2F%2Fmicrosoftgraph.chinacloudapi.cn%2Fuser.read&response_mode=fragment&state=12345&nonce=678910&prompt=none&login_hint={your-username}

借助 prompt=none 参数,此请求立即成功或立即失败,并返回应用程序。Thanks to the prompt=none parameter, this request will either succeed or fail immediately and return to your application. 成功的响应会通过 response_mode 参数中指定的方法,发送到位于所指示的 redirect_uri 的应用。A successful response will be sent to your app at the indicated redirect_uri, using the method specified in the response_mode parameter.

成功的响应Successful response

使用 response_mode=fragment 的成功响应如下所示:A successful response using response_mode=fragment looks like:

GET https://localhost/myapp/#
access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...
&state=12345
&token_type=Bearer
&expires_in=3599
&scope=https%3A%2F%2Fmicrosoftgraph.chinacloudapi.cn%2Fdirectory.read
参数Parameter 说明Description
access_token 如果 response_type 包含 token,则包含该参数。Included if response_type includes token. 应用请求的访问令牌,在本例中为 Microsoft Graph 的访问令牌。The access token that the app requested, in this case for the Microsoft Graph. 访问令牌不得进行解码或检查,应当作为不透明字符串对待。The access token shouldn't be decoded or otherwise inspected, it should be treated as an opaque string.
token_type 始终为 BearerWill always be Bearer.
expires_in 表示令牌有效的秒数(针对缓存目的)。Indicates the number of seconds the token is valid, for caching purposes.
scope 表示 access_token 的有效范围。Indicates the scope(s) for which the access_token will be valid. 可能不包括所有请求的范围(如果它们不适用于用户)。May not include all of the scopes requested, if they were not applicable to the user.
id_token 有符号 JSON Web 令牌 (JWT)。A signed JSON Web Token (JWT). 如果 response_type 包含 id_token,则包含该参数。Included if response_type includes id_token. 应用可以解码此令牌的段,以请求已登录用户的相关信息。The app can decode the segments of this token to request information about the user who signed in. 应用可以缓存并显示值,但不应依赖于这些值来获取任何授权或安全边界。The app can cache the values and display them, but it shouldn't rely on them for any authorization or security boundaries. 有关 id_tokens 的详细信息,请参阅id_token参考For more information about id_tokens, see the id_token reference.
注意: 仅当已请求 openid 作用域时提供。Note: Only provided if openid scope was requested.
state 如果请求中包含 state 参数,响应中就应该出现相同的值。If a state parameter is included in the request, the same value should appear in the response. 应用应该验证请求和响应中的 state 值是否完全相同。The app should verify that the state values in the request and response are identical.

错误响应Error response

错误响应还可能发送到 redirect_uri ,因此应用可以适当地对其进行处理。Error responses may also be sent to the redirect_uri so the app can handle them appropriately. 如果是 prompt=none,预期的错误为:In the case of prompt=none, an expected error will be:

GET https://localhost/myapp/#
error=user_authentication_required
&error_description=the+request+could+not+be+completed+silently
参数Parameter 说明Description
error 可用于分类发生的错误类型与响应错误的错误码字符串。An error code string that can be used to classify types of errors that occur, and can be used to react to errors.
error_description 帮助开发人员识别身份验证错误根本原因的特定错误消息。A specific error message that can help a developer identify the root cause of an authentication error.

如果在 iframe 请求中收到此错误,用户必须再次以交互方式登录以检索新令牌。If you receive this error in the iframe request, the user must interactively sign in again to retrieve a new token. 可以选择对应用程序合理的任何方式处理这种情况。You can choose to handle this case in whatever way makes sense for your application.

刷新令牌Refreshing tokens

隐式授权不提供刷新令牌。The implicit grant does not provide refresh tokens. id_tokenaccess_token 很快就会过期,因此应用必须准备好定期刷新这些令牌。Both id_tokens and access_tokens will expire after a short period of time, so your app must be prepared to refresh these tokens periodically. 若要刷新任一类型的令牌,可以通过使用 prompt=none 参数控制 Microsoft 标识平台的行为,来执行上述同一隐藏的 iframe 请求。To refresh either type of token, you can perform the same hidden iframe request from above using the prompt=none parameter to control the identity platform's behavior. 若要接收新的 id_token,请务必使用 response_typescope=openid 中的 id_token,以及 nonce 参数。If you want to receive a new id_token, be sure to use id_token in the response_type and scope=openid, as well as a nonce parameter.

发送注销请求Send a sign out request

OpenID Connect end_session_endpoint 允许应用向 Microsoft 标识平台终结点发送请求以结束用户的会话,并清除 Microsoft 标识平台终结点设置的 Cookie。The OpenID Connect end_session_endpoint allows your app to send a request to the Microsoft identity platform endpoint to end a user's session and clear cookies set by the Microsoft identity platform endpoint. 要完全将用户从 Web 应用程序注销,应用应结束自己与用户的会话(通常通过清除令牌缓存或删除 Cookie 实现),然后将浏览器重定向到:To fully sign a user out of a web application, your app should end its own session with the user (usually by clearing a token cache or dropping cookies), and then redirect the browser to:

https://login.partner.microsoftonline.cn/{tenant}/oauth2/v2.0/logout?post_logout_redirect_uri=https://localhost/myapp/
参数Parameter 类型Type 说明Description
tenant 必填required 请求路径中的 {tenant} 值可用于控制哪些用户可以登录应用程序。The {tenant} value in the path of the request can be used to control who can sign into the application. 可以使用的值包括 commonorganizationsconsumers 和租户标识符。The allowed values are common, organizations, consumers, and tenant identifiers. 有关详细信息,请参阅协议基础知识For more detail, see protocol basics.
post_logout_redirect_uri 建议recommended 注销完成后用户应返回到的 URL。The URL that the user should be returned to after logout completes. 此值必须与为应用程序注册的重定向 URI 之一匹配。This value must match one of the redirect URIs registered for the application. 如果未包含,Microsoft 标识平台终结点会向用户显示一条常规消息。If not included, the user will be shown a generic message by the Microsoft identity platform endpoint.

后续步骤Next steps