当前位置: 首页 > 知识库问答 >
问题:

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

花俊雄
2023-03-14

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

在调试这个程序的过程中,我试着制作出最简单的应用程序。此应用程序正在尝试使用Graph从Azure Active Directory读取用户的配置文件。

我在AAD中注册了我的应用程序,所以我有一个租户、客户ID和客户机密。现在,我已经在AAD和Graph API下授予了它所有的权限(用于测试目的)。我可以从AAD获取令牌,但当我使用此令牌调用Graph API时,我会得到401-未经授权的令牌,并出现访问令牌验证错误。

我搜索了这个错误,但没有找到任何似乎适用的东西。

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

我从各种样品中抓取了一些碎片,试图让它发挥作用。代码如下:

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-未经授权。

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

谢啦!

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

共有2个答案

王鹏飞
2023-03-14

我相信您只需单击“所需权限”菜单中的“授予权限”。

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

如果有帮助,请告诉我!

谯嘉懿
2023-03-14

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

  1. 您获取的访问令牌对调用无效https://graph.microsoft.com 。请注意,令牌中的aud声明具有应用程序id 0000000 2-0000-0000-c000-000000000000,这是AAD图形API的应用程序id,是一个类似但不同的endpoint

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

您的代码似乎要遵循V1过程,因此您需要确保获取令牌的POST请求具有以下参数:授予类型客户端id客户端机密资源

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

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

var资源=”https://graph.microsoft.com“;

请求参数。添加(“资源”,资源);

如果有帮助,请告诉我。

 类似资料:
  • 因此,我正在尝试对第三方 API 提供程序进行 API 调用。在我的nodejs应用程序中接收新令牌没有问题,但是当我尝试在get函数中使用它时,我只收到403错误。但是,如果我通过Postman获得令牌,它就可以正常工作(在应用程序中),这对我来说似乎很奇怪? 如果我尝试在Postman中的get调用中使用从nodejs应用程序获取的令牌,那也是一样的,它不会起作用。 我已经多次检查从我的nod

  • 我正在使用laravel 5.4开发一个api 尝试使用API控制器登录时 它给我以下错误: {FatalThrowableError调用未定义的方法Illumate\Auth\TokenGuard::attempt()}

  • 我正在编写一个应用程序,调用来自Flutter的google fit rest api。 我需要使用(https://pub.dev/packages/google_sign_in)与谷歌签名。我可以毫无问题地获得一个令牌(见是否有人设法从谷歌登录(Flutter)获得id令牌),但如何获得一个新的令牌时,它是过期的? 我不想要求用户每小时登录并获得一个新的令牌

  • 问题内容: 在集成到更大的应用程序之前,我正在尝试测试一个概念验证的命令行应用程序。我想要做的是使用此示例使用NSURLSession下载一些数据。但是,如果使用简单的OS X命令行应用程序中给出的示例,则该应用程序将在检索数据之前退出。 如何使用NSURLSession从独立的命令行应用程序下载数据?我所读的内容是使用NSRunLoop,但是我还没有在Swift中找到明确的示例,因此,如果NSR

  • 调用swap的惯用法是: 这样,就可以为std命名空间之外的用户定义类型重载交换。 我们是否应该以相同的方式调用开始和结束? 或者我们应该写:

  • 我想在我的Android Flatter应用程序中包括Firebase应用程序检查Firebase存储。因此,我遵循官方文件:https://firebase.flutter.dev/docs/app-check/usage. 这是我的静态编程语言Main Active: 这是我的主要观点: 我还将其添加到我的应用程序/构建中。格拉德尔 当我向firebase storage发出请求时,我希望在我