【问题标题】:Calling Microsoft Graph via REST API using Application token使用应用程序令牌通过 REST API 调用 Microsoft Graph
【发布时间】:2017-10-06 21:43:18
【问题描述】:

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

在尝试调试时,我尝试制作最简单的应用程序。此应用只是尝试使用 Graph 从 Azure Active Directory 读取用户的配置文件。

我在 AAD 中注册了我的应用程序,因此我有一个租户、客户端 ID 和一个客户端密码。至此,我已经在 AAD 和 Graph API 下授予了它所有权限(用于测试目的)。我能够从 AAD 获得一个令牌,但是当我使用这个令牌调用 Graph API 时,我得到了401 - UnauthorizedAccess 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>"));

第二个电话返回 401 - Unauthorized。

有没有人发现我做错了什么,或者我应该检查一下?

谢谢!

编辑:这是来自令牌的 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"
}

【问题讨论】:

  • 令牌的受众有问题。 “00000002-0000-0000-c000-000000000000”是App ID for the AAD Graph API。此外,您没有“角色”声明,这意味着您无论如何都无法调用任何 API...
  • 是的……很确定问题出在这里:requestParameters.Add("scope", resource)。应该是requestParameters.Add("resource", resource)resource 应该是https://graph.microsoft.com。查看身份验证过程的详细信息here
  • 谢谢,我试试看!
  • 感谢肖恩 - 成功了!
  • 另一个问题,如果可以的话:这里的文档表明应该通过“范围”:developer.microsoft.com/en-us/graph/docs/concepts/… - 应该更正吗?

标签: azure-active-directory microsoft-graph-api


【解决方案1】:

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

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

在查看您的代码以了解资源问题发生在哪里时,我们可以看到您将V1V2 身份验证过程稍微混淆了。

您的代码似乎要遵循 V1 程序,因此您需要确保您的 POST 获取令牌的请求具有以下参数: grant_typeclient_idclient_secretresource

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

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

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

requestParameters.Add("resource", resource);

如果这有帮助,请告诉我。

【讨论】:

  • 这很有帮助!谢谢。我想我会调查 V2 端点,但我的 V1 工作正常!
【解决方案2】:

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

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

如果这有帮助,请告诉我!

【讨论】:

  • 感谢您的回复 - 但我已经这样做了。我会编辑问题 - 谢谢!
  • 你能分享你的访问令牌吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-20
  • 2020-05-27
  • 1970-01-01
  • 1970-01-01
  • 2022-11-11
  • 1970-01-01
相关资源
最近更新 更多