Microsoft Graph令牌不包含任何权限,或者无法理解权限

时间:2019-01-17 11:39:45

标签: c# oauth-2.0 office365 microsoft-graph

我正在使用Microsoft Graph,并且已经创建了一个读取特定用户邮件的应用程序。

但是,在获得访问令牌并尝试读取邮件文件夹后,我收到401未经授权的答案。详细信息是:

令牌不包含任何权限,或者权限无法理解

这似乎是一条非常清晰的信息,但是很遗憾,我无法找到解决方案。 这是我到目前为止所做的:

权限为: enter image description here enter image description here  -编写以下代码以获取访问令牌:

 // client_secret retrieved from secure storage (e.g. Key Vault)
 string tenant_id = "xxxx.onmicrosoft.com";
 ConfidentialClientApplication client = new ConfidentialClientApplication(
 "..",
 $"https://login.microsoftonline.com/{tenant_id}/",
 "https://dummy.example.com", // Not used, can be any valid URI 
 new ClientCredential(".."),
 null, // Not used for pure client credentials
 new TokenCache());
   string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
   AuthenticationResult result = client.AcquireTokenForClientAsync(scopes).Result;
   string token = result.AccessToken;

到目前为止,一切都很好。我确实得到了令牌。

现在我想阅读邮件文件夹:

url = "https://graph.microsoft.com/v1.0/users/{username}/mailFolders";
handler = (HttpWebRequest)WebRequest.Create(url);
handler.Method = "GET";
handler.ContentType = "application/json";
handler.Headers.Add("Authorization", "Bearer " + token);
response = (HttpWebResponse)handler.GetResponse();
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
{
    returnValue = sr.ReadToEnd();
}

这一次我收到一条401消息,其中包含详细信息:

令牌不包含任何权限,或者权限无法理解。

我已经搜索了互联网,但找不到答案来解释为什么我的令牌没有权限。

感谢您的时间!

更新1

如果我使用Graph Explorer来阅读邮件文件夹,则可以正常工作。此外:如果我从浏览器中获取令牌ID,并在第二段代码中使用它,那么我也将得到结果。因此,问题实际上是我从第一步收到的令牌。

1 个答案:

答案 0 :(得分:3)

为确保此操作如您期望的那样,您应明确声明您希望为哪个租户获取访问令牌。 (在此租户中,该应用程序当然应该已经获得管理员的同意。)

使用特定于租户的端点代替“公共”令牌端点:

string url = "https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token";

{tenant-id}是租户(Guid)的租户ID或任何经过验证的域名。)

我也强烈建议反对自己构建令牌请求,如您在问题中所显示的。这对于教育目的可能是有用的,但从长远来看往往会变得不安全且容易出错。

您可以使用各种库来代替。下面是使用Microsoft Authentication Library (MSAL) for .NET的示例:

// client_secret retrieved from secure storage (e.g. Key Vault)
string tenant_id = "contoso.onmicrosoft.com";
ConfidentialClientApplication client = new ConfidentialClientApplication(
    client_id,
    $"https://login.microsoftonline.com/{tenant_id}/",
    "https://dummy.example.com", // Not used, can be any valid URI 
    new ClientCredential(client_secret),
    null, // Not used for pure client credentials
    new TokenCache());

string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
AuthenticationResult result = client.AcquireTokenForClientAsync(scopes).Result
string token = result.AccessToken;
// ... use token