Microsoft Graph 无法提供服务(通过 C# 代码进行客户端凭据身份验证)

问题描述 投票:0回答:1

我想从我的个人邮箱中检索一些电子邮件附件。

如果我使用可以从 Graph Explorer 复制的令牌,一切都会正常工作,即使它似乎已过期并且需要多次检索“刷新”的令牌。

var tokenProvider = new TokenProvider(access_token); // access_token from Microsoft Graph Explorer.

var authenticationProvider = new BaseBearerTokenAuthenticationProvider(tokenProvider);

var graphServiceClient = new GraphServiceClient(authenticationProvider);

var user = graphServiceClient.Users[userId];

var messages = await user.Messages.GetAsync(); // Works fine.

尽管如此,当我从 C# 代码生成令牌时,我收到了 Service Unavailable 异常。

执行了太多次重试。发送请求时重试次数超过 3 次。 (HTTP 请求失败,状态代码:ServiceUnavailable)。

var tokenEndpoint = $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token";

using var httpClient = new HttpClient();

var requestBody = $"client_id={clientId}&client_secret={clientSecret}&redirect_uri=http://localhost&grant_type=client_credentials&scope=https://graph.microsoft.com/.default";

var request = new HttpRequestMessage(HttpMethod.Post, tokenEndpoint)
{
    Content = new StringContent(requestBody, Encoding.UTF8, "application/x-www-form-urlencoded")
};

var response = await httpClient.SendAsync(request);

response.EnsureSuccessStatusCode();

var responseContent = await response.Content.ReadAsStringAsync();

var data = JsonConvert.DeserializeObject<JObject>(responseContent);

var access_token = $"{data["access_token"]}";

var tokenProvider = new TokenProvider(access_token);

var authenticationProvider = new BaseBearerTokenAuthenticationProvider(tokenProvider);

var graphServiceClient = new GraphServiceClient(authenticationProvider);

var user = graphServiceClient.Users[userId];

var messages = await user.Messages.GetAsync(); // Service Unavailable.

我还通过 Postman 获得了一个明显有效的令牌,其中包含 200 状态代码。我也尝试更改 tenatId、clientId 等,但这会导致其他问题。

有人知道导致问题的原因吗?

c# azure microsoft-graph-api microsoft-entra-id
1个回答
0
投票

如本MS Doc中所述,您需要使用委托权限,该权限适用于交互流或授权代码流等委托流。从个人帐户检索消息。

最初,我通过在“移动和桌面应用程序”平台中添加重定向URI注册了一个多租户Entra ID应用程序,如下所示:

enter image description here

现在,我在上面的应用程序注册中添加了

Mail.Read
权限,即委托类型:

enter image description here

要使用交互流进行身份验证,请确保启用公共客户端选项:

enter image description here

在我的例子中,我使用了下面的示例代码,该代码使用交互式流程进行身份验证,并通过使用个人帐户登录成功获得了响应

using Azure.Identity;
using Microsoft.Graph;
using Microsoft.Graph.Models.ODataErrors;

var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "common";
var clientId = "appId";

var options = new InteractiveBrowserCredentialOptions
{
    TenantId = tenantId,
    ClientId = clientId,
    AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
    RedirectUri = new Uri("http://localhost"),
};

var interactiveCredential = new InteractiveBrowserCredential(options);

var graphClient = new GraphServiceClient(interactiveCredential, scopes);

try
{
    var messages = await graphClient.Me.Messages.GetAsync(requestConfiguration =>
    {
        requestConfiguration.QueryParameters.Expand = new string[] { "attachments" };
    });

    foreach (var message in messages.Value)
    {
        Console.WriteLine($"Subject: {message.Subject}");
        Console.WriteLine($"Message ID: {message.Id}");
        if (message.Attachments.Any())
        {
            Console.WriteLine("Attachments:");
            foreach (var attachment in message.Attachments)
            {
                Console.WriteLine($"  Attachment Id: {attachment.Id}");
                Console.WriteLine($"  Attachment Name: {attachment.Name}");
            }
        }
        else
        {
            Console.WriteLine("No attachments found.");
        }
        Console.WriteLine("-------------------------------------------");
    }
}
catch (ODataError odataError)
{
    Console.WriteLine(odataError.Error.Code);
    Console.WriteLine(odataError.Error.Message);
}

回复:

enter image description here

参考:

使用图形 API 访问个人邮箱 - Carl Zhu 的 Microsoft 问答 - MSFT

© www.soinside.com 2019 - 2024. All rights reserved.