使用应用程序令牌通过REST API调用Microsoft Graph

Phi*_*Mar 2 azure-active-directory microsoft-graph

我正在尝试使用REST API调用Microsoft Graph,但遇到了一些问题。我的应用程序最终将是部署到Azure的Web应用程序,我需要在没有登录用户的情况下通过REST调用Graph。

在尝试调试时,我尝试制作了最简单的应用程序。该应用程序正试图使用​​Graph从Azure Active Directory中读取用户的配置文件。

我在AAD中注册了我的应用,因此我有一个租户,客户ID和客户密码。至此,我已经在AAD和Graph API下授予了所有许可(出于测试目的)。我可以从AAD获得令牌,但是当我使用该令牌调用Graph API时,我会获得401 - Unauthorizedwith Access Token Validation Error

我已经搜索了此错误,却没有发现任何适用的方法。

编辑:添加权限后,我还向我的应用程序授予了权限。

我已经从各种样本中抓取了一些片段,以尝试使其正常工作。这是代码:

var tenant = "tenant ID";
var clientID = "app ID";

// I've tried graph.microsoft.com and graph.microsoft.com/.default
var resource = "https://graph.microsoft.com/user.read.all";
var secret = "client secret";

string token;

using(var webClient = new WebClient())
{
    var requestParameters = new NameValueCollection();
    requestParameters.Add("scope", resource);
    requestParameters.Add("client_id", clientID);
    requestParameters.Add("grant_type", "client_credentials");
    requestParameters.Add("client_secret", secret);

    var url = $"https://login.microsoftonline.com/{tenant}/oauth2/token";
    var responseBytes = await webClient.UploadValuesTaskAsync(url, "POST", requestParameters);
    var responseBody = Encoding.UTF8.GetString(responseBytes);

    var jsonObject = Newtonsoft.Json.JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>(responseBody);
    token = jsonObject.Value<string>("access_token");
}
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);

var response = await client.GetAsync(new Uri("https://graph.microsoft.com/v1.0/user/<user ID>"));
Run Code Online (Sandbox Code Playgroud)

第二个电话是401-未经授权。

有人看到我做错了什么,还是应该检查?

谢谢!

编辑:这是令牌中的JSON,使用Fiddler解码并删除了租户和客户端ID:

{
    "typ": "JWT",
    "alg": "RS256",
    "x5t": "HHByKU-0DqAqMZh6ZFPd2VWaOtg",
    "kid": "HHByKU-0DqAqMZh6ZFPd2VWaOtg"
} 
{
    "aud": "spn:00000002-0000-0000-c000-000000000000",
    "iss": "https://sts.windows.net/<tenant id>/",
    "iat": 1507313785,
    "nbf": 1507313785,
    "exp": 1507317685,
    "aio": "Y2VgYCguP8H/lUPs5seMpgeOze3vAA==",
    "appid": "~client id~",
    "appidacr": "1",
    "idp": "https://sts.windows.net/~tenant id~/",
    "oid": "37df6326-7ed1-4b88-a57c-b82319a5cb07",
    "sub": "37df6326-7ed1-4b88-a57c-b82319a5cb07",
    "tenant_region_scope": "NA",
    "tid": "~tenant id~",
    "uti": "IspHJJNqjUKWjvsWmXhDAA",
    "ver": "1.0"
}
Run Code Online (Sandbox Code Playgroud)

Sha*_*izi 5

在查看了代码示例和您在问题中编辑的访问令牌后,我可以指出一些问题:

  1. 您获得的访问令牌对于调用无效https://graph.microsoft.com。请注意,aud令牌中的声明具有应用程序ID 00000002-0000-0000-c000-000000000000,这是AAD Graph API应用程序ID,这是一个相似但不同的端点。
  2. 您拥有的令牌没有任何role声明,该令牌用于向尝试在“仅应用程序”流中调用的客户端应用程序授予访问权限。这可能是第一个问题的结果,修复资源后,还应填充role声明。

当查看您的代码以查看发生资源问题的位置时,我们可以看到您略微混淆了V1V2身份验证过程。

您的代码似乎想跟随V1的过程,所以你需要确保你的POST要求得到令牌具有以下参数: grant_typeclient_idclient_secretresource

在代码示例中,您似乎添加了一个scope参数,而不是一个resource参数。这与我们支持动态同意的V2方法一致,在该方法中,您可以定义获取令牌时想要的范围,但这不适用于V1端点。

相反,您应该在代码中更新这两行:

var resource = "https://graph.microsoft.com";

requestParameters.Add("resource", resource);

让我知道是否有帮助。


Sha*_*izi 0

我相信您在这里需要做的就是单击所需权限菜单中的“授予权限”。

在此输入图像描述

基本上,向您的应用程序添加权限还不够好。您的应用程序还必须获得用户同意,才能授予其使用“仅限应用程序”权限调用图形 API 的权限。授予权限按钮是向您的应用程序授予同意的一种方式。另一种方法是简单地登录应用程序,这将提示用户同意。

让我知道这是否有帮助!