第一次使用Microsoft Graph API时,遇到了一些我不太确定的事情。
我应该构建一些概念证明web应用程序,我基本上可以从应用程序(使用它自己的身份)查看业务驱动器(或站点/组驱动器),并向其上传/下载文件。然而,在找出我做错了什么的时候,我遇到了一些问题。
我写了一些帮助器函数来帮助我获取令牌,但它似乎就是不起作用。
下面是我写的函数:
public static async Task<string> GetAccessToken() {
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(tokenUrl);
// We want the response to be JSON.
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Build up the data to POST.
List<KeyValuePair<string, string>> postData = new List<KeyValuePair<string, string>>();
postData.Add(new KeyValuePair<string, string>("grant_type", "client_credentials"));
postData.Add(new KeyValuePair<string, string>("client_id", clientId));
postData.Add(new KeyValuePair<string, string>("client_secret", clientSecret));
postData.Add(new KeyValuePair<string, string>("scope", scope));
FormUrlEncodedContent requestBody = new FormUrlEncodedContent(postData);
//Request Token
var request = await client.PostAsync(tokenUrl, requestBody).ConfigureAwait(false);
var response = await request.Content.ReadAsStringAsync();
var responseData = JsonConvert.DeserializeObject(response);
//Return Token
return ((dynamic)responseData).access_token;
}
}
public static async Task<dynamic> GetSite(string accessToken) {
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(baseUrl);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Add the Authorization header with the AccessToken.
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
// create the URL string.
string url = string.Format("{0}sites/root/", baseUrl);
// make the request
HttpResponseMessage response = await client.GetAsync(url).ConfigureAwait(false);
// parse the response and return the data.
string jsonString = await response.Content.ReadAsStringAsync();
object responseData = JsonConvert.DeserializeObject(jsonString);
return (dynamic)responseData;
}
}每当我试图获得一个网站,它似乎不能正常工作。所以我想我可以在Postman中尝试这些请求,看看它们是否可以在那里工作,但是在setting up Postman for application API calls之后,我通常会得到这样的响应:
{
"error": {
"code": "generalException",
"message": "An unspecified error has occurred.",
"innerError": {
"date": "SomeTimeLateAtNight",
"request-id": "WhateverTheRequestIDis",
"client-request-id": "WhateverTheClientRequestIDis"
}
}
}我是不是做错了什么?在我的应用注册中,我在here中找到的接口权限设置为"Sites.ReadAll, Sites.ReadWriteAll"。我通过jwt.ms运行我的令牌,发现我的角色设置为:
"APIConnectors.ReadWrite.All", "Sites.Selected", "Directory.ReadWrite.All", "Sites.Read.All", "Sites.ReadWrite.All", "Sites.Manage.All", "Files.ReadWrite.All", "Directory.Read.All", "Files.Read.All", "APIConnectors.Read.All", "Sites.FullControl.All"这些应该是我读/写/查看它们所需要的,对吗?所以我有点困惑。
为了好玩,我试着通过Microsoft Graph Explorer完成我的请求,但最终一切都像预期的那样工作。我还从Graph Explorer请求中提取了身份验证令牌,并将其推送到我的Postman请求中,它最终正常工作,这让我相信我以某种方式搞砸了Azure应用程序API权限。对下一步该怎么做有什么建议吗?我不确定我的解释是否足够清楚,但我应该如何修复它,以便作为应用程序的请求获得实际结果,而不是我得到的一般异常?(因为应用程序会自己下载/上传,而不需要任何其他用户登录。)
发布于 2021-01-20 12:59:19
我为你的代码创建了一个新的Azure AD应用程序以进行快速测试,以下是我为我的应用程序授予的权限,请确保你已单击“授予管理员同意”按钮以完成授予权限过程:

我的测试代码如下,基于一个控制台应用程序:
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
namespace GraphAPITest
{
class Program
{
static void Main(string[] args)
{
var accessToken = GetAccessToken().GetAwaiter().GetResult();
Console.WriteLine(GetSite(accessToken).GetAwaiter().GetResult());
}
public static async Task<string> GetAccessToken()
{
using (var client = new HttpClient())
{
var clientId = "<app id>";
var clientSecret = "<secret>";
var tenant = "<your tenant name/id>";
var scope = @"https://graph.microsoft.com/.default";
var tokenUrl = @"https://login.microsoftonline.com/"+ tenant + "/oauth2/v2.0/token";
client.BaseAddress = new Uri(tokenUrl);
// We want the response to be JSON.
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Build up the data to POST.
List<KeyValuePair<string, string>> postData = new List<KeyValuePair<string, string>>();
postData.Add(new KeyValuePair<string, string>("grant_type", "client_credentials"));
postData.Add(new KeyValuePair<string, string>("client_id", clientId));
postData.Add(new KeyValuePair<string, string>("client_secret", clientSecret));
postData.Add(new KeyValuePair<string, string>("scope", scope));
FormUrlEncodedContent requestBody = new FormUrlEncodedContent(postData);
//Request Token
var request = await client.PostAsync(tokenUrl, requestBody).ConfigureAwait(false);
var response = await request.Content.ReadAsStringAsync();
var responseData = JsonConvert.DeserializeObject(response);
//Return Token
return ((dynamic)responseData).access_token;
}
}
public static async Task<dynamic> GetSite(string accessToken)
{
using (var client = new HttpClient())
{
var baseUrl = "https://graph.microsoft.com/v1.0/";
client.BaseAddress = new Uri(baseUrl);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Add the Authorization header with the AccessToken.
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
// create the URL string.
string url = string.Format("{0}sites/root/", baseUrl);
// make the request
HttpResponseMessage response = await client.GetAsync(url).ConfigureAwait(false);
// parse the response and return the data.
string jsonString = await response.Content.ReadAsStringAsync();
object responseData = JsonConvert.DeserializeObject(jsonString);
return (dynamic)responseData;
}
}
}
}结果:

如果你有任何进一步的问题,请告诉我。
发布于 2021-01-20 14:21:57
检查权限类型为“应用”或“委派”。

如果是应用权限,则相应权限的状态栏为绿色

如果您看到一条警告消息,表示尚未授予管理员许可。在使用该应用程序之前,您必须获得同意。这个错误很可能就是这种情况。
发布于 2021-01-20 17:44:17
您可能已经添加了必要的权限,但忘记提供由Satya标识的“管理员同意”。另外,我建议使用微软的MSAL库来处理这个流程,像这样的https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-v2-netcore-daemon,代码的可读性要少得多。
https://stackoverflow.com/questions/65802798
复制相似问题