Microsoft 标识平台和 OAuth 2.0 客户端凭据流Microsoft identity platform and the OAuth 2.0 client credentials flow

适用于:Applies to:
  • Microsoft 标识平台终结点Microsoft identity platform endpoint

可通过 RFC 6749 中指定的 OAuth 2.0 客户端凭据授予(有时称为“双重 OAuth” ),使用应用程序标识来访问 Web 托管的资源。You can use the OAuth 2.0 client credentials grant specified in RFC 6749, sometimes called two-legged OAuth, to access web-hosted resources by using the identity of an application. 这种授予通常用于必须在后台运行的服务器间交互,不需要立即与用户交互。This type of grant is commonly used for server-to-server interactions that must run in the background, without immediate interaction with a user. 此类应用程序通常称为守护程序 或服务帐户 。These types of applications are often referred to as daemons or service accounts.

OAuth 2.0 客户端凭据授权流允许 Web 服务(机密客户端)在调用其他 Web 服务时使用它自己的凭据(而不是模拟用户)进行身份验证。The OAuth 2.0 client credentials grant flow permits a web service (confidential client) to use its own credentials, instead of impersonating a user, to authenticate when calling another web service. 在这种情况下,客户端通常是中间层 Web 服务、后台程序服务或网站。In this scenario, the client is typically a middle-tier web service, a daemon service, or a web site. 为了进行更高级别的保证,Microsoft 标识平台还允许调用服务将证书(而不是共享机密)用作凭据。For a higher level of assurance, the Microsoft identity platform also allows the calling service to use a certificate (instead of a shared secret) as a credential.

Note

Microsoft 标识平台终结点并非支持所有 Azure AD 方案和功能。The Microsoft identity platform endpoint doesn't support all Azure AD scenarios and features. 若要确定是否应使用 Microsoft 标识平台终结点,请阅读 Microsoft 标识平台限制To determine whether you should use the Microsoft identity platform endpoint, read about Microsoft identity platform limitations.

在较典型的 三重 OAuth中,客户端应用程序有权代表特定用户访问资源。In the more typical three-legged OAuth, a client application is granted permission to access a resource on behalf of a specific user. 该权限通常在许可过程中由用户委托给应用程序。The permission is delegated from the user to the application, usually during the consent process. 但是,在客户端凭据(双重 OAuth )流中,权限直接授予应用程序本身。However, in the client credentials (two-legged OAuth) flow, permissions are granted directly to the application itself. 应用向资源出示令牌时,该资源强制要求应用本身而不是用户拥有执行操作的授权。When the app presents a token to a resource, the resource enforces that the app itself has authorization to perform an action and not the user.

协议图Protocol diagram

整个客户端凭据流类似于下图。The entire client credentials flow looks similar to the following diagram. 本文稍后介绍每个步骤。We describe each of the steps later in this article.

显示客户端凭据流的关系图

获取直接授权Get direct authorization

应用往往通过以下两种方式之一接收直接授权来访问资源:An app typically receives direct authorization to access a resource in one of two ways:

这两种方法在 Azure AD 中很常见,建议用于执行客户端凭据流的客户端和资源。These two methods are the most common in Azure AD and we recommend them for clients and resources that perform the client credentials flow. 资源也可选择以其他方式向其客户端授权。A resource can also choose to authorize its clients in other ways. 每个资源服务器可选择最适合其应用程序的方法。Each resource server can choose the method that makes the most sense for its application.

访问控制列表Access control lists

资源提供程序可根据它所知并对其授予特定级别访问权限的应用程序(客户端)ID 列表,强制实施授权检查。A resource provider might enforce an authorization check based on a list of application (client) IDs that it knows and grants a specific level of access to. 资源从 Microsoft 标识平台终结点接收令牌时,可以将此令牌解码,并从 appidiss 声明中提取客户端的应用程序 ID。When the resource receives a token from the Microsoft identity platform endpoint, it can decode the token and extract the client's application ID from the appid and iss claims. 然后将应用程序与它所维护的访问控制列表 (ACL) 相比较。Then it compares the application against an access control list (ACL) that it maintains. ACL 的粒度和方法可能因资源不同而有较大差异。The ACL's granularity and method might vary substantially between resources.

常见用例是使用 ACL 对 Web 应用程序或 Web API 运行测试。A common use case is to use an ACL to run tests for a web application or for a web API. Web API 可能仅向特定客户端授予部分完全权限。The web API might grant only a subset of full permissions to a specific client. 若要在 API 上运行端到端测试,请创建测试客户端,以便从 Microsoft 标识平台终结点获取令牌并将令牌发送到 API。To run end-to-end tests on the API, create a test client that acquires tokens from the Microsoft identity platform endpoint and then sends them to the API. 然后,API 会检查测试客户端应用程序 ID 的 ACL,以获取对 API 整个功能的完全访问权限。The API then checks the ACL for the test client's application ID for full access to the API's entire functionality. 如果使用这种 ACL,不仅需要验证调用方的 appid 值,而且还要验证令牌的 iss 值是否受信任。If you use this kind of ACL, be sure to validate not only the caller's appid value but also validate that the iss value of the token is trusted.

对于组织拥有的数据,建议通过应用程序权限获取必要的授权。For data owned by organizations, we recommend that you get the necessary authorization through application permissions.

应用程序权限Application permissions

可使用 API 公开一组应用程序权限,而不是使用 ACL。Instead of using ACLs, you can use APIs to expose a set of application permissions. 应用程序权限由组织管理员向应用程序授予,并且只可用于访问该组织与其员工所拥有的数据。An application permission is granted to an application by an organization's administrator, and can be used only to access data owned by that organization and its employees. 例如,Microsoft Graph 公开多个应用程序权限来执行以下操作:For example, Microsoft Graph exposes several application permissions to do the following:

  • 读取所有邮箱中的邮件Read mail in all mailboxes
  • 在所有邮箱中读取和写入邮件Read and write mail in all mailboxes
  • 以任何用户的身份发送邮件Send mail as any user
  • 读取目录数据Read directory data

有关应用程序权限的详细信息,请转到 Microsoft GraphFor more information about application permissions, go to Microsoft Graph.

若要在应用中使用应用程序权限,请执行后续部分所述的步骤。To use application permissions in your app, follow the steps discussed in the next sections.

在应用注册门户中请求权限Request the permissions in the app registration portal

  1. 通过新的应用注册(预览版)体验注册和创建应用。Register and create an app through the new App registrations (Preview) experience.
  2. 在应用注册(预览版)体验中转到你的应用程序。Go to your application in the App registrations (Preview) experience. 导航到“证书和机密”部分,并添加一个新的客户端机密,因为至少需要使用一个客户端机密来请求令牌。 Navigate to the Certificates & secrets section, and add a new client secret, because you'll need at least one client secret to request a token.
  3. 找到“API 权限” 部分,然后添加应用所需的应用程序权限Locate the API permissions section, and then add the application permissions that your app requires.
  4. 保存 应用注册。Save the app registration.

在构建使用应用程序权限的应用程序时,应用通常需要一个页面或视图,使管理员能够批准应用的权限。Typically, when you build an application that uses application permissions, the app requires a page or view on which the admin approves the app's permissions. 此页面可以是应用登录流的一部分、应用设置的一部分,或者专用的“连接”流。This page can be part of the app's sign-in flow, part of the app's settings, or it can be a dedicated "connect" flow. 在许多情况下,合理的结果是只有在用户使用工作或学校帐户登录后,应用才显示此“连接”视图。In many cases, it makes sense for the app to show this "connect" view only after a user has signed in with a work or school account.

如果让用户登录到应用,可以在请求用户批准应用程序权限之前识别该用户所属组织。If you sign the user into your app, you can identify the organization to which the user belongs to before you ask the user to approve the application permissions. 尽管在严格意义上不需要这样做,但这有助于为用户带来更直观的体验。Although not strictly necessary, it can help you create a more intuitive experience for your users. 若要将用户登录,请遵循 Microsoft 标识平台协议教程To sign the user in, follow our Microsoft identity platform protocol tutorials.

向目录管理员请求权限Request the permissions from a directory admin

准备好向组织管理员请求权限时,可将用户重定向到 Microsoft 标识平台管理员许可终结点When you're ready to request permissions from the organization's admin, you can redirect the user to the Microsoft identity platform admin consent endpoint.

Tip

尝试在 Postman 中执行此请求!Try executing this request in Postman! (为获得最佳效果,请使用自己的应用 ID - 教程应用程序不会请求有用的权限。)尝试在 Postman 中运行此请求(Use your own app ID for best results - the tutorial application won't request useful permissions.) Try running this request in Postman

// Line breaks are for legibility only.

GET https://login.partner.microsoftonline.cn/{tenant}/adminconsent?
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&state=12345
&redirect_uri=http://localhost/myapp/permissions
// Pro tip: Try pasting the following request in a browser.
https://login.partner.microsoftonline.cn/common/adminconsent?client_id=6731de76-14a6-49ae-97bc-6eba6914391e&state=12345&redirect_uri=http://localhost/myapp/permissions
参数Parameter 条件Condition 说明Description
tenant 必须Required 要向其请求权限的目录租户。The directory tenant that you want to request permission from. 此参数可采用 GUID 或友好名称格式。This can be in GUID or friendly name format. 如果不知道用户属于哪个租户并想让他们登录到任一租户,请使用 commonIf you don't know which tenant the user belongs to and you want to let them sign in with any tenant, use common.
client_id 必须Required Azure 门户 - 应用注册体验分配给应用的应用程序(客户端)IDThe Application (client) ID that the Azure portal - App registrations experience assigned to your app.
redirect_uri 必须Required 要向其发送响应,供应用处理的重定向 URI。The redirect URI where you want the response to be sent for your app to handle. 它必须与门户中注册的其中一个重定向 URI 完全匹配,否则必须经过 URL 编码并可包含其他路径段。It must exactly match one of the redirect URIs that you registered in the portal, except that it must be URL encoded, and it can have additional path segments.
state 建议Recommended 同时随令牌响应返回的请求中所包含的值。A value that's included in the request that's also returned in the token response. 可以是所需的任何内容的字符串。It can be a string of any content that you want. 该 state 用于在身份验证请求出现之前,于应用中编码用户的状态信息,例如之前所在的页面或视图。The state is 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.

此时,Azure AD 强制要求只有租户管理员可以登录来完成请求。At this point, Azure AD enforces that only a tenant administrator can sign into complete the request. 系统会要求管理员批准在应用注册门户中针对应用请求的所有直接应用程序权限。The administrator will be asked to approve all the direct application permissions that you have requested for your app in the app registration portal.

成功的响应Successful response

如果管理员批准了应用程序的权限,成功响应如下所示:If the admin approves the permissions for your application, the successful response looks like this:

GET http://localhost/myapp/permissions?tenant=a8990e1f-ff32-408a-9f8e-78d3b9139b95&state=state=12345&admin_consent=True
参数Parameter 说明Description
tenant 向应用程序授予所请求权限的目录租户(采用 GUID 格式)。The directory tenant that granted your application the permissions that it requested, in GUID format.
state 同样随令牌响应返回的请求中所包含的值。A value that is included in the request that also is returned in the token response. 可以是所需的任何内容的字符串。It can be a string of any content that you want. 该 state 用于在身份验证请求出现之前,于应用中编码用户的状态信息,例如之前所在的页面或视图。The state is 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.
admin_consent 设置为 TrueSet to True.
错误响应Error response

如果管理员未批准应用程序的权限,失败响应如下所示:If the admin does not approve the permissions for your application, the failed response looks like this:

GET http://localhost/myapp/permissions?error=permission_denied&error_description=The+admin+canceled+the+request
参数Parameter 说明Description
error 可用于将错误分类,以及对错误做出反应的错误代码字符串。An error code string that you can use to classify types of errors, and which you can use to react to errors.
error_description 可帮助识别错误根本原因的特定错误消息。A specific error message that can help you identify the root cause of an error.

从应用预配终结点收到成功响应后,应用便已获得它所请求的直接应用程序权限。After you've received a successful response from the app provisioning endpoint, your app has gained the direct application permissions that it requested. 现在,可以请求所需的资源令牌。Now you can request a token for the resource that you want.

获取令牌Get a token

获取应用程序的必要授权后,可以继续获取 API 的访问令牌。After you've acquired the necessary authorization for your application, proceed with acquiring access tokens for APIs. 若要使用客户端凭据授予获取令牌,请将 POST 请求发送到 /token Microsoft 标识平台终结点:To get a token by using the client credentials grant, send a POST request to the /token Microsoft identity platform endpoint:

Tip

尝试在 Postman 中执行此请求!Try executing this request in Postman! (为获得最佳效果,请使用自己的应用 ID - 教程应用程序不会请求有用的权限。)尝试在 Postman 中运行此请求(Use your own app ID for best results - the tutorial application won't request useful permissions.) Try running this request in Postman

第一种情况:使用共享机密访问令牌请求First case: Access token request with a shared secret

POST /{tenant}/oauth2/v2.0/token HTTP/1.1           //Line breaks for clarity
Host: login.partner.microsoftonline.cn
Content-Type: application/x-www-form-urlencoded

client_id=535fb089-9ff3-47b6-9bfb-4f1264799865
&scope=https%3A%2F%2Fmicrosoftgraph.chinacloudapi.cn%2F.default
&client_secret=qWgdYAmab0YSkuL1qKv5bPX
&grant_type=client_credentials
// Replace {tenant} with your tenant! 
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 'client_id=535fb089-9ff3-47b6-9bfb-4f1264799865&scope=https%3A%2F%2Fmicrosoftgraph.chinacloudapi.cn%2F.default&client_secret=qWgdYAmab0YSkuL1qKv5bPX&grant_type=client_credentials' 'https://login.partner.microsoftonline.cn/{tenant}/oauth2/v2.0/token'
参数Parameter 条件Condition 说明Description
tenant 必须Required 应用程序计划对其进行操作的目录租户,采用 GUID 或域名格式。The directory tenant the application plans to operate against, in GUID or domain-name format.
client_id 必须Required 分配给应用的应用程序 ID。The application ID that's assigned to your app. 可以在注册应用的门户中找到此信息。You can find this information in the portal where you registered your app.
scope 必须Required 在此请求中针对 scope 参数传递的值应该是所需资源的资源标识符(应用程序 ID URI),并附有 .default 后缀。The value passed for the scope parameter in this request should be the resource identifier (application ID URI) of the resource you want, affixed with the .default suffix. 在 Microsoft Graph 示例中,该值为 https://microsoftgraph.chinacloudapi.cn/.defaultFor the Microsoft Graph example, the value is https://microsoftgraph.chinacloudapi.cn/.default.
此值告知 Microsoft 标识平台终结点:在为应用配置的所有直接应用程序权限中,终结点应该为与要使用的资源关联的权限颁发令牌。This value tells the Microsoft identity platform endpoint that of all the direct application permissions you have configured for your app, the endpoint should issue a token for the ones associated with the resource you want to use. 若要了解有关 /.default 范围的详细信息,请参阅许可文档To learn more about the /.default scope, see the consent documentation.
client_secret 必须Required 在应用注册门户中为应用生成的客户端机密。The client secret that you generated for your app in the app registration portal. 在发送客户端密码之前必须对其进行 URL 编码。The client secret must be URL-encoded before being sent.
grant_type 必须Required 必须设置为 client_credentialsMust be set to client_credentials.

第二种情况:使用证书访问令牌请求Second case: Access token request with a certificate

POST /{tenant}/oauth2/v2.0/token HTTP/1.1               // Line breaks for clarity
Host: login.partner.microsoftonline.cn
Content-Type: application/x-www-form-urlencoded

scope=https%3A%2F%2Fmicrosoftgraph.chinacloudapi.cn%2F.default
&client_id=97e0a5b7-d745-40b6-94fe-5f77d35c6e05
&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
&client_assertion=eyJhbGciOiJSUzI1NiIsIng1dCI6Imd4OHRHeXN5amNScUtqRlBuZDdSRnd2d1pJMCJ9.eyJ{a lot of characters here}M8U3bSUKKJDEg
&grant_type=client_credentials
参数Parameter 条件Condition 说明Description
tenant 必须Required 应用程序计划对其进行操作的目录租户,采用 GUID 或域名格式。The directory tenant the application plans to operate against, in GUID or domain-name format.
client_id 必须Required 分配给应用的应用程序(客户端)ID。The application (client) ID that's assigned to your app.
scope 必须Required 在此请求中针对 scope 参数传递的值应该是所需资源的资源标识符(应用程序 ID URI),并附有 .default 后缀。The value passed for the scope parameter in this request should be the resource identifier (application ID URI) of the resource you want, affixed with the .default suffix. 在 Microsoft Graph 示例中,该值为 https://microsoftgraph.chinacloudapi.cn/.defaultFor the Microsoft Graph example, the value is https://microsoftgraph.chinacloudapi.cn/.default.
此值告知 Microsoft 标识平台终结点:在为应用配置的所有直接应用程序权限中,终结点应该为与要使用的资源关联的权限颁发令牌。This value informs the Microsoft identity platform endpoint that of all the direct application permissions you have configured for your app, it should issue a token for the ones associated with the resource you want to use. 若要了解有关 /.default 范围的详细信息,请参阅许可文档To learn more about the /.default scope, see the consent documentation.
client_assertion_type 必须Required 该值必须设置为 urn:ietf:params:oauth:client-assertion-type:jwt-bearerThe value must be set to urn:ietf:params:oauth:client-assertion-type:jwt-bearer.
client_assertion 必须Required 断言(JSON Web 令牌),需使用作为凭据向应用程序注册的证书进行创建和签名。An assertion (a JSON web token) that you need to create and sign with the certificate you registered as credentials for your application. 有关如何注册证书以及断言的格式,请阅读证书凭据的相关信息。Read about certificate credentials to learn how to register your certificate and the format of the assertion.
grant_type 必须Required 必须设置为 client_credentialsMust be set to client_credentials.

请注意,参数几乎与共享密钥请求的参数相同,只不过 client_secret 参数替换为两个参数:client_assertion_type 和 client_assertion。Notice that the parameters are almost the same as in the case of the request by shared secret except that the client_secret parameter is replaced by two parameters: a client_assertion_type and client_assertion.

成功的响应Successful response

成功响应如下所示:A successful response looks like this:

{
  "token_type": "Bearer",
  "expires_in": 3599,
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1uQ19WWmNBVGZNNXBP..."
}
参数Parameter 说明Description
access_token 请求的访问令牌。The requested access token. 应用可以使用此令牌验证受保护的资源,例如验证 Web API。The app can use this token to authenticate to the secured resource, such as to a Web API.
token_type 指示令牌类型值。Indicates the token type value. Microsoft 标识平台支持的唯一类型是 bearerThe only type that Microsoft identity platform supports is bearer.
expires_in 访问令牌有效的时间长短(以秒为单位)。The amount of time that an access token is valid (in seconds).

错误响应Error response

错误响应如下所示:An error response looks like this:

{
  "error": "invalid_scope",
  "error_description": "AADSTS70011: The provided value for the input parameter 'scope' is not valid. The scope https://foo.microsoft.com/.default is not valid.\r\nTrace ID: 255d1aef-8c98-452f-ac51-23d051240864\r\nCorrelation ID: fb3d2015-bc17-4bb9-bb85-30c5cf1aaaa7\r\nTimestamp: 2016-01-09 02:02:12Z",
  "error_codes": [
    70011
  ],
  "timestamp": "2016-01-09 02:02:12Z",
  "trace_id": "255d1aef-8c98-452f-ac51-23d051240864",
  "correlation_id": "fb3d2015-bc17-4bb9-bb85-30c5cf1aaaa7"
}
参数Parameter 说明Description
error 可用于对发生的错误分类以及对错误做出反应的错误代码字符串。An error code string that you can use to classify types of errors that occur, and to react to errors.
error_description 可帮助识别身份验证错误根本原因的特定错误消息。A specific error message that might help you identify the root cause of an authentication error.
error_codes 可帮助诊断的 STS 特定错误代码列表。A list of STS-specific error codes that might help with diagnostics.
timestamp 发生错误的时间。The time when the error occurred.
trace_id 可帮助进行诊断的请求的唯一标识符。A unique identifier for the request to help with diagnostics.
correlation_id 可帮助跨组件进行诊断的请求的唯一标识符。A unique identifier for the request to help with diagnostics across components.

使用令牌Use a token

获取令牌后,使用该令牌对资源发出请求。Now that you've acquired a token, use the token to make requests to the resource. 令牌过期时,向 /token 终结点重复该请求,即可获取全新的访问令牌。When the token expires, repeat the request to the /token endpoint to acquire a fresh access token.

GET /v1.0/me/messages
Host: https://microsoftgraph.chinacloudapi.cn
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...
// Pro tip: Try the following command! (Replace the token with your own.)
curl -X GET -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbG...." 'https://microsoftgraph.chinacloudapi.cn/v1.0/me/messages'

代码示例和其他文档Code samples and other documentation

阅读 Microsoft 身份验证库中的客户端凭据概述文档Read the client credentials overview documentation from the Microsoft Authentication Library

示例Sample 平台Platform 说明Description
active-directory-dotnetcore-daemon-v2active-directory-dotnetcore-daemon-v2 .NET Core 2.1 控制台.NET Core 2.1 Console 一个简单的 .NET Core 应用程序,该应用程序显示某个租户的用户在使用应用程序的标识查询 Microsoft Graph,而不是代表用户来查询。A simple .NET Core application that displays the users of a tenant querying the Microsoft Graph using the identity of the application, instead of on behalf of a user. 该示例还演示了使用证书进行身份验证的变体。The sample also illustrates the variation using certificates for authentication.
active-directory-dotnet-daemon-v2active-directory-dotnet-daemon-v2 ASP.NET MVCASP.NET MVC 一个 Web 应用程序,该应用程序使用应用程序的标识来同步 Microsoft Graph 的数据,而不是代表用户来同步。A web application that syncs data from the Microsoft Graph using the identity of the application, instead of on behalf of a user.