【问题标题】:Microsoft Graph The token contains no permissions, or permissions cannot be understoodMicrosoft Graph 令牌不包含权限,或权限无法理解
【发布时间】:2019-06-11 14:32:46
【问题描述】:

我正在使用 Microsoft Graph,并创建了一个可以读取特定用户邮件的应用。

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

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

这似乎是一个非常明确的信息,但不幸的是我无法找到解决方案。 这是我到目前为止所做的:

权限是: - 编写以下代码来获取访问令牌:

 // 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,然后在我的第二段代码中使用它,那么我也会得到一个结果。所以,问题实际上是我从第一步收到的令牌。

【问题讨论】:

  • 您可以将您的令牌粘贴到jwt.io。在那里,您可以检查有效负载是否真的列出了所需的权限。否则,请重新检查您授予的权限,并可能为您的应用程序重新运行管理员同意。
  • 嗨奥利弗,感谢您的回复。我已将副本粘贴到验证器中。解码后的响应似乎没问题,但老实说我不知道​​在哪里寻找权限。
  • 如果你看一下解码后的有效载荷,有一些众所周知的 jwt 属性,如iatnbfexp。再低一点,有一个属性scp。这包含您可以访问的所有范围。这是一个空格分隔的列表,应该包含文本 Mail.ReadMail.ReadWrite。如果不是这样,你没有权限。
  • 这可能是问题所在:我根本没有 scp 属性。
  • 那么您请求 graph.microsoft.com 令牌的方式有问题。不知道是什么,但我请求the application token differently then you

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


【解决方案1】:

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

使用特定于租户的端点,而不是“通用”令牌端点:

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

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

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

您可以使用各种库来代替。下面,一个使用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

【讨论】:

  • 嗨菲利普,谢谢你的回答。我确实实现了这段代码,但是在使用令牌请求邮件 API 时,我仍然收到相同的错误响应。我确定注册该应用程序一定有问题。我赞成您的回答,因为我感谢图书馆的建议和努力!
  • 您完全确定已授予权限吗?您可以在 Azure 门户 > 企业应用 >(查找您的应用)> 权限下进行确认。另外,您能否更新您的问题,使其与您最新版本的代码相匹配?
  • 我刚刚在问题中添加了权限。这些我可以在 apps.dev.microsoft.com(第一张图片)和 portal.azure.com(第二张图片)上看到
  • 您似乎仍在使用 common 端点来获取令牌 (https://login.microsoftonline.com/common/),而不是特定于租户的端点 (https://login.microsoftonline.com/{tenant-id})。您是否尝试过使用特定于租户的端点? (将$"https://login.microsoftonline.com/common/", 行替换为$"https://login.microsoftonline.com/{tenant_id}/",,就像在我的示例中一样。)
  • 对不起,你是对的。我确实更改了租户 ID,但忘记在 de url 中使用此变量。然而结果是一样的。
猜你喜欢
  • 1970-01-01
  • 2020-06-19
  • 1970-01-01
  • 1970-01-01
  • 2016-09-29
  • 2020-06-25
  • 2021-04-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多