C# Microsoft Graph访问我

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

我有一个应用程序设置,使用Azure AD(工作或学校帐户)将用户登录到该应用程序。我还希望能够使用委派权限从此应用程序查询Microsoft Graph。我相信我的安装程序使用的是应用程序权限,我看不出我缺少什么来正确安装。该应用程序是ASP.NET Core 2应用程序

在我的Startup.cs中,我有以下代码

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;
    }
}