用于调用 Web API 的守护程序应用 - 获取令牌Daemon app that calls web APIs - acquire a token

在构建机密客户端应用程序以后,可以获取应用的令牌,方法是调用 AcquireTokenForClient,传递作用域,然后强制刷新令牌。After you've constructed a confidential client application, you can acquire a token for the app by calling AcquireTokenForClient, passing the scope, and optionally forcing a refresh of the token.

请求的作用域Scopes to request

请求客户端凭据流时,其作用域是资源的名称后跟 /.defaultThe scope to request for a client credential flow is the name of the resource followed by /.default. 此表示法告知 Azure Active Directory (Azure AD) 使用在应用程序注册过程中静态声明的应用程序级权限This notation tells Azure Active Directory (Azure AD) to use the application-level permissions declared statically during application registration. 另外,这些 API 权限必须由租户管理员授予。Also, these API permissions must be granted by a tenant administrator.

ResourceId = "someAppIDURI";
var scopes = new [] {  ResourceId+"/.default"};

Azure AD (v1.0) 资源Azure AD (v1.0) resources

用于客户端凭据的作用域应该始终为资源 ID 后跟 /.defaultThe scope used for client credentials should always be the resource ID followed by /.default.

重要

当 MSAL 向接受 1.0 版访问令牌的资源请求访问令牌时,Azure AD 将获取最后一个斜杠前面的所有内容并将其用作资源标识符,从请求的范围内分析所需的受众。When MSAL requests an access token for a resource that accepts a version 1.0 access token, Azure AD parses the desired audience from the requested scope by taking everything before the last slash and using it as the resource identifier. 因此,就像 Azure SQL 数据库 (https://database.chinacloudapi.cn) 一样,如果资源需要以斜杠结尾的受众(对于 Azure SQL 数据库为 https://database.chinacloudapi.cn/),你将需要请求作用域 https://database.chinacloudapi.cn//.defaultSo if, like Azure SQL Database (https://database.chinacloudapi.cn), the resource expects an audience that ends with a slash (for Azure SQL Database, https://database.chinacloudapi.cn/), you'll need to request a scope of https://database.chinacloudapi.cn//.default. (请注意双斜杠。)另请参阅 MSAL.NET 问题 #747:将省略资源 URL 的尾部斜杠,因为该斜杠会导致 SQL 身份验证失败(Note the double slash.) See also MSAL.NET issue #747: Resource url's trailing slash is omitted, which caused sql auth failure.

AcquireTokenForClient APIAcquireTokenForClient API

为了获取应用的令牌,你将使用 AcquireTokenForClient 或其等效命令,具体取决于平台。To acquire a token for the app, you'll use AcquireTokenForClient or its equivalent, depending on the platform.

using Microsoft.Identity.Client;

// With client credentials flows, the scope is always of the shape "resource/.default" because the
// application permissions need to be set statically (in the portal or by PowerShell), and then granted by
// a tenant administrator.
string[] scopes = new string[] { "https://microsoftgraph.chinacloudapi.cn/.default" };

AuthenticationResult result = null;
try
{
 result = await app.AcquireTokenForClient(scopes)
                  .ExecuteAsync();
}
catch (MsalUiRequiredException ex)
{
    // The application doesn't have sufficient permissions.
    // - Did you declare enough app permissions during app creation?
    // - Did the tenant admin grant permissions to the application?
}
catch (MsalServiceException ex) when (ex.Message.Contains("AADSTS70011"))
{
    // Invalid scope. The scope has to be in the form "https://resourceurl/.default"
    // Mitigation: Change the scope to be as expected.
}

协议Protocol

如果还没有适用于所选语言的库,你可能希望直接使用协议:If you don't yet have a library for your chosen language, you might want to use the protocol directly:

第一种情况:使用共享机密访问令牌请求First case: Access the token request by using 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

第二种情况:使用证书访问令牌请求Second case: Access the token request by using 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

有关详细信息,请参阅协议文档:Microsoft 标识平台和 OAuth 2.0 客户端凭据流For more information, see the protocol documentation: Microsoft identity platform and the OAuth 2.0 client credentials flow.

应用程序令牌缓存Application token cache

在 MSAL.NET 中,AcquireTokenForClient 使用应用程序令牌缓存。In MSAL.NET, AcquireTokenForClient uses the application token cache. (所有其他 AcquireTokenXX 方法都使用用户令牌缓存。)不要在调用 AcquireTokenForClient 之前调用 AcquireTokenSilent,因为 AcquireTokenSilent 使用“用户” 令牌缓存。(All the other AcquireTokenXX methods use the user token cache.) Don't call AcquireTokenSilent before you call AcquireTokenForClient, because AcquireTokenSilent uses the user token cache. AcquireTokenForClient 会检查应用程序令牌缓存本身并对其进行更新。AcquireTokenForClient checks the application token cache itself and updates it.

故障排除Troubleshooting

你是否使用过 resource/.default 作用域?Did you use the resource/.default scope?

如果出现一条错误消息,指出所使用的作用域无效,则表明你并未使用 resource/.default 作用域。If you get an error message telling you that you used an invalid scope, you probably didn't use the resource/.default scope.

如果在调用 API 时出现错误“权限不足,无法完成该操作”, 则租户管理员需要授予对应用程序的权限。If you get an Insufficient privileges to complete the operation error when you call the API, the tenant administrator needs to grant permissions to the application. 请查看上面的步骤 6:注册客户端应用。See step 6 of Register the client app above. 通常会看到如下错误:You'll typically see an error that looks like this error:

Failed to call the web API: Forbidden
Content: {
  "error": {
    "code": "Authorization_RequestDenied",
    "message": "Insufficient privileges to complete the operation.",
    "innerError": {
      "request-id": "<guid>",
      "date": "<date>"
    }
  }
}

后续步骤Next steps