c# - 使用 Microsoft Graph 获取电子邮件,无需任何用户交互
问题描述
我要做的就是获取用户 ID 的电子邮件,其他用户无需登录其 Microsoft 帐户即可访问该用户 ID。我查看了许多 SO 帖子(this)、代码示例(this、this)并查看了 OpenID 和其他文档的规范(this),但仍然无法弄清楚。
我已经在 azure 门户中注册了应用程序并授予了所需的权限。使用示例应用程序,我可以获取用户列表,但不能获取电子邮件列表。我比较了用户查询和电子邮件查询的请求标头。两者看起来都一样。有人可以告诉我我做错了什么吗?
代码如下:
启动.Auth.cs
public static string clientId = "<CLIENT ID>";
public static string clientSecret = <CLIENT SECRET>;
private static string authority = "https://login.microsoftonline.com/common/v2.0";
public static string redirectUri = "https://localhost:44316/";
private void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
Authority = authority,
RedirectUri = redirectUri,
PostLogoutRedirectUri = redirectUri,
//Scope = "openid profile offline_access Mail.Read",
Scope = "email profile openid offline_access User.Read Mail.Read",
//ResponseType = "id_token",
ResponseType = "code id_token",
TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = false, NameClaimType = "name" },
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = this.OnAuthenticationFailedAsync,
SecurityTokenValidated = this.OnSecurityTokenValidatedAsync
}
});
}
同步控制器.cs
private const string AuthorityFormat = "https://login.microsoftonline.com/{0}/v2.0";
private const string MSGraphScope = "https://graph.microsoft.com/.default";
//private const string MSGraphQuery = "https://graph.microsoft.com/v1.0/users";
//private const string MSGraphQuery = "https://graph.microsoft.com/v1.0/me";
private const string MSGraphQuery = "https://graph.microsoft.com/v1.0/me/messages";
public async Task GetAsync(string tenantId)
{
MSALCache appTokenCache = new MSALCache(Startup.clientId);
// Get a token for the Microsoft Graph. If this line throws an exception for
// any reason, we'll just let the exception be returned as a 500 response
// to the caller, and show a generic error message to the user.
ConfidentialClientApplication daemonClient = new ConfidentialClientApplication(Startup.clientId, string.Format(AuthorityFormat, tenantId), Startup.redirectUri,
new ClientCredential(Startup.clientSecret), null, appTokenCache.GetMsalCacheInstance());
AuthenticationResult authResult = await daemonClient.AcquireTokenForClientAsync(new[] { MSGraphScope });
HttpClient client = new HttpClient();
// Uses SendAsync
/*HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, MSGraphQuery);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
//request.Headers.Add("client-request-id", System.Guid.NewGuid().ToString());
//request.Headers.Add("return-client-request-id", "true");
HttpResponseMessage response = await client.SendAsync(request);*/
// Uses GetAsync
client.BaseAddress = new System.Uri(MSGraphQuery);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + authResult.AccessToken);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(MSGraphQuery);
}
编辑 1: 以下是用户列表(工作)和电子邮件列表(不工作)的请求和响应值:
Request body to fetch user list (working):
{Method: GET, RequestUri: 'https://graph.microsoft.com/v1.0/users', Version: 1.1, Content: <null>, Headers:
{
Accept: application/json
Authorization: Bearer eyJ0eXAiOiJKV...
}}
Response when fetching user list (working):
{StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Transfer-Encoding: chunked
request-id: 02034f96-f519-4f5f-b47d-efb98dff0072
client-request-id: 02034f96-f519-4f5f-b47d-efb98dff0072
x-ms-ags-diagnostic: {"ServerInfo":{"DataCenter":"South India","Slice":"SliceC","Ring":"5","ScaleUnit":"002","Host":"AGSFE_IN_8","ADSiteName":"INS"}}
OData-Version: 4.0
Duration: 76.0712
Strict-Transport-Security: max-age=31536000
Cache-Control: private
Date: Fri, 02 Nov 2018 12:36:51 GMT
Content-Type: application/json; odata.metadata=minimal; odata.streaming=true; IEEE754Compatible=false; charset=utf-8
}}
Request body to fetch emails (not working):
{Method: GET, RequestUri: 'https://graph.microsoft.com/v1.0/me/mailFolders('Inbox')/messages', Version: 1.1, Content: <null>, Headers:
{
Accept: application/json
Authorization: Bearer eyJ0eXAiOiJKV...
}}
Response when fetching list of emails (not working):
{StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Transfer-Encoding: chunked
request-id: 5b728866-b132-404f-9986-70fc56e57c3c
client-request-id: 5b728866-b132-404f-9986-70fc56e57c3c
x-ms-ags-diagnostic: {"ServerInfo":{"DataCenter":"South India","Slice":"SliceC","Ring":"5","ScaleUnit":"002","Host":"AGSFE_IN_6","ADSiteName":"INS"}}
Duration: 4205.8126
Strict-Transport-Security: max-age=31536000
Cache-Control: private
Date: Fri, 02 Nov 2018 12:43:03 GMT
Content-Type: application/json
}}
解决方案
您Client_Credentials
用于验证应用程序并使用/me
REST 调用中的路径。这两个不能一起工作。
在幕后/me
被转换为当前经过身份验证的用户(即/users/user@domain
。由于您没有经过身份验证的用户,因此 Graph 根本不可能将您的请求转换为可操作的调用。
您需要使用 theirid
或 theiruserPrincipalName
明确引用用户:
/v1.0/users/123e4567-e89b-12d3-a456-426655440000/mailFolders('Inbox')/messages
/v1.0/users/user@yourdomain.com/mailFolders('Inbox')/messages
推荐阅读
- python-3.x - KeyError:“[Int64Index([1960, 1961, 1962, 1963, 1964], dtype='int64')] 均不在 [列] 中”
- sql - go-GORM 无法插入值
- javascript - 在 IIS 10 中浏览时未加载图像
- azure - 无法创建 Azure Web App Bot,出现身份验证错误
- python - 此功能的完美 numpy 实现
- json - 在 .NET Core API 中处理带有 JSON 列表的 POST
- c# - 在下拉菜单中显示所有国家
- sql - 如何在不允许回滚活动的情况下清除表“策略”中的所有记录
- locust - 在特定数量的请求后停止蝗虫
- python - 失败:TypeError:机器人框架中的预期字符串或缓冲区(RIDE 工具)