C# Microsoft Graph访问我
我有一个应用程序设置,使用Azure AD(工作或学校帐户)将用户登录到该应用程序。我还希望能够使用委派权限从此应用程序查询Microsoft Graph。我相信我的安装程序使用的是应用程序权限,我看不出我缺少什么来正确安装。该应用程序是ASP.NET Core 2应用程序 在我的Startup.cs中,我有以下代码C# Microsoft Graph访问我,c#,asp.net,azure,microsoft-graph-api,C#,Asp.net,Azure,Microsoft Graph Api,我有一个应用程序设置,使用Azure AD(工作或学校帐户)将用户登录到该应用程序。我还希望能够使用委派权限从此应用程序查询Microsoft Graph。我相信我的安装程序使用的是应用程序权限,我看不出我缺少什么来正确安装。该应用程序是ASP.NET Core 2应用程序 在我的Startup.cs中,我有以下代码 public void ConfigureServices(IServiceCollection services) { services.AddAuthenticatio
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddAzureAd(options => Configuration.Bind("AzureAd", options))
.AddCookie();
services.AddMvc();
services.AddSingleton(Configuration);
services.AddSingleton<IGraphAuthProvider, GraphAuthProvider>();
services.AddTransient<IGraphSDKHelper, GraphSDKHelper>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
从我所读到的一切来看,这看起来像是我正在尝试做的正确设置。现在在主页控制器中,我有以下代码
public async Task<IActionResult> Index(string email)
{
// Get users's email.
email = email ?? User.Identity.Name;
ViewData["Email"] = email;
// Get user's id for token cache.
var identifier = User.FindFirst(Startup.ObjectIdentifierType)?.Value;
// Initialize the GraphServiceClient.
var graphClient = _graphSdkHelper.GetAuthenticatedClient(identifier);
ViewData["Response"] = await GraphService.GetUserJson(graphClient, email);
ViewData["Response"] = await GraphService.GetMeJson(graphClient, email);
//ViewData["Picture"] = await GraphService.GetPictureBase64(graphClient, email);
var groups = await GraphService.GetGroups(graphClient);
return View();
}
这行代码表示GetMeJson确实可以工作,并且通过了一个错误,它看起来像
var user = await graphClient.Me.Request().GetAsync();
return JsonConvert.SerializeObject(user, Formatting.Indented);
public GraphServiceClient GetAuthenticatedClient(string userId)
{
_graphClient = new GraphServiceClient("https://graph.microsoft.com/beta", new DelegateAuthenticationProvider(
async (requestMessage) =>
{
// Passing tenant ID to the sample auth provider to use as a cache key
AccessToken = await _authProvider.GetUserAccessTokenAsync(userId);
// Append the access token to the request
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
}));
return _graphClient;
}
最后一段代码是GetAuthenticatedClient,它看起来像
var user = await graphClient.Me.Request().GetAsync();
return JsonConvert.SerializeObject(user, Formatting.Indented);
public GraphServiceClient GetAuthenticatedClient(string userId)
{
_graphClient = new GraphServiceClient("https://graph.microsoft.com/beta", new DelegateAuthenticationProvider(
async (requestMessage) =>
{
// Passing tenant ID to the sample auth provider to use as a cache key
AccessToken = await _authProvider.GetUserAccessTokenAsync(userId);
// Append the access token to the request
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
}));
return _graphClient;
}
我收到的错误消息如下:
Microsoft.Graph.ServiceException:
Code: Request_ResourceNotFound
Message: Resource '40f381c1-55f3-4295-99e3-0309a704374e' does not
exist or one of its queried reference-property objects
are not present.
有人能帮我克服这个障碍吗?这样我就可以作为经过身份验证的用户调用Graph API了
***********Marc要求的其他信息*************
该应用程序通过portal.azure.com注册,并具有以下权限
在Microsoft Graph下
在应用程序权限下,User.Read.All、Directory.Read.All、Group.Read.All
在“委派权限”下,配置文件(查看用户的基本配置文件)、电子邮件(查看用户的电子邮件地址)、Directory.Read.All。Group.Read.All,User.Read.All,User.ReadBasic.All
在WindowsAzure活动目录下
在委派权限下:User.Read(登录并读取用户配置文件)
我现在知道我不需要应用程序权限,可以在某个时候删除它们,但我没有权限这样做,需要让其他人为我做
**********调试令牌*********
我在线路上设置了一个断点
AccessToken = await _authProvider.GetUserAccessTokenAsync(userId);
然后将它得到的AccessToken放到caleb.net中,得到以下结果
{
typ: "JWT",
nonce: "bunch of letters",
alg: "RS256",
x5t: "bunch of letters",
kid: "bunch of letters"
}.
{
aud: "https://graph.microsoft.com/",
iss: "https://sts.windows.net/dde15eeb-a6bd-46a2-9f03-d44429074ecf/",
iat: 1503942101,
nbf: 1503942101,
exp: 1503946001,
aio: "bunch of letters",
app_displayname: "Test App",
appid: "Guid",
appidacr: "1",
e_exp: 262800,
idp: "https://sts.windows.net/dde15eeb-a6bd-46a2-9f03-d44429074ecf/",
oid: "Guid",
roles: [
"Group.Read.All",
"Directory.Read.All",
"User.Read.All"
],
sub: "Guid",
tid: "Guid",
uti: "bunch of letters",
ver: "1.0"
}.
[signature]
正如您所怀疑的,它只是作为应用程序权限,而不是授权权限。那么,这段代码在哪里获取令牌有什么问题呢。我显然没有在这里进行正确类型的身份验证,但我不知道我做错了什么
public async Task<string> GetUserAccessTokenAsync(string userId)
{
TokenCache userTokenCache = new SessionTokenCache(userId, _memoryCache).GetCacheInstance();
try
{
AuthenticationContext authContext = new AuthenticationContext(_aadInstance, userTokenCache);
ClientCredential credential = new ClientCredential(_appId, _appSecret);
AuthenticationResult result = await authContext.AcquireTokenAsync(_graphResourceId, credential);
return result.AccessToken;
}
catch (Exception ex)
{
return null;
}
}
公共异步任务GetUserAccessTokenAsync(字符串用户ID)
{
TokenCache userTokenCache=new SessionTokenCache(userId,_memoryCache).GetCacheInstance();
尝试
{
AuthenticationContext authContext=新的AuthenticationContext(_aadInstance,userTokenCache);
ClientCredential=新的ClientCredential(\u appId,\u appSecret);
AuthenticationResult=等待authContext.AcquireTokenAsync(\u graphResourceId,credential);
返回result.AccessToken;
}
捕获(例外情况除外)
{
返回null;
}
}
您是如何注册您的应用程序的?您申请了哪些范围?通常,当我看到
/me
不工作时,这是因为您使用的是客户端凭据,而不是授权代码授权流(客户端凭据在上下文中没有用户,因此me
没有指向帐户).我在问题本身添加了一个新的部分,其中包含有关申请注册的信息,并阅读了与您提到的有关无法访问我的内容相同的内容,但是我找不到问题所在。我怀疑问题在于GetUserAccessTokenAsync
没有为https://graph.microsoft.com/
资源。也就是说,我不确定在这种情况下,它为什么适用于用户[电子邮件]
。值得一看的是JWT令牌本身。您可以解码实际的令牌@,这可能会对此有所帮助。GetUserAccessTokenAsync
是您自己的方法还是您正在引用的库的一部分?让我们看看。
public async Task<string> GetUserAccessTokenAsync(string userId)
{
TokenCache userTokenCache = new SessionTokenCache(userId, _memoryCache).GetCacheInstance();
try
{
AuthenticationContext authContext = new AuthenticationContext(_aadInstance, userTokenCache);
ClientCredential credential = new ClientCredential(_appId, _appSecret);
AuthenticationResult result = await authContext.AcquireTokenAsync(_graphResourceId, credential);
return result.AccessToken;
}
catch (Exception ex)
{
return null;
}
}