.Net core 应用程序无法从 Microsoft Graph API 获取用户详细信息? [英] .Net core App unable to get user details from Microsoft Graph API?

查看:29
本文介绍了.Net core 应用程序无法从 Microsoft Graph API 获取用户详细信息?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Net 核心 Web API 项目.我在 azure AD 中为 Web API 应用程序注册了应用程序.我配置了 swagger 并在 Azure AD 中注册了另一个应用程序.我正在尝试基于组对我的 webapis 进行授权.在 appsettings.json 我有所有的值.

下面是我的初创公司的样子.

public void ConfigureServices(IServiceCollection services){services.AddSingleton();服务.AddAuthentication(o =>{o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;}).AddJwtBearer(o =>{o.Authority = azureActiveDirectoryOptions.Authority;o.TokenValidationParameters = 新的 TokenValidationParameters{ValidAudiences = 新列表<字符串>{azureActiveDirectoryOptions.AppIdUri,azureActiveDirectoryOptions.ClientId},ValidateIssuer = 真};});services.AddScoped();services.AddAuthorization(options =>{options.AddPolicy("GroupsCheck", policy =>{策略.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);policy.RequireAuthenticatedUser();policy.Requirements.Add(new GroupsCheckRequirement("2a39995a-8fd1-410e-99e2-11cf6046090d"));});});services.AddMvc(options =>{var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().建造();options.Filters.Add(new AuthorizeFilter(policy));}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);services.AddSwaggerGen(c =>{c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });c.AddSecurityDefinition("oauth2", new OAuth2Scheme{类型 = "oauth2",流 = "隐式",AuthorizationUrl = swaggerUIOptions.AuthorizationUrl,TokenUrl = swaggerUIOptions.TokenUrl});c.AddSecurityRequirement(new Dictionary>{{ "oauth2", new[] { "readAccess", "writeAccess" } }});});}//这个方法被运行时调用.使用此方法配置 HTTP 请求管道.公共无效配置(IApplicationBuilder 应用程序,IHostingEnvironment 环境){如果 (env.IsDevelopment()){app.UseDeveloperExceptionPage();}别的{app.UseHsts();}app.UseHttpsRedirection();app.UseSwagger();app.UseSwaggerUI(c =>{c.OAuthClientId(swaggerUIOptions.ClientId);c.OAuthClientSecret(swaggerUIOptions.ClientSecret);c.OAuthRealm(azureActiveDirectoryOptions.ClientId);c.OAuthAppName("Swagger");c.OAuthAdditionalQueryStringParams(new { resource = azureActiveDirectoryOptions.ClientId });c.SwaggerEndpoint("/swagger/v1/swagger.json", "我的 API V1");});app.UseAuthentication();app.UseMvc();}

当我使用

现在我的招摇中有授权按钮.每当我尝试授权时,它都会要求我输入用户名和密码.身份验证按预期工作.接下来我想点击/api/values/users/{id}.控制器如下所示.

 [Authorize(Policy = "GroupsCheck")][路由(api/[控制器]")][接口控制器]公共类 ValuesController : ControllerBase{}

我需要基于组的授权.在启动时,我添加了策略.

services.AddAuthorization(options =>{options.AddPolicy("GroupsCheck", policy =>{策略.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);policy.RequireAuthenticatedUser();policy.Requirements.Add(new GroupsCheckRequirement("2a39995a-8fd1-410e-99e2-11cf6046090d"));});});

下面是我的 GroupsCheckHandler.cs

 protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context,GroupsCheckRequirement 要求){GraphServiceClient 客户端 = 等待 MicrosoftGraphClient.GetGraphServiceClient();//试图让用户和力为我工作var user = await client.Me.Request().GetAsync();//这里发生异常var groupList = await client.Groups.Request().GetAsync();变量结果 = 假;foreach(groupList 中的 var 组){if (requirement.groups.Equals(group.Id)){结果=真;}}如果(结果){上下文.成功(要求);}}

下面是我的 MicrosoftGraphClient.cs

public static async TaskGetGraphServiceClient(){//使用访问令牌和 microsoft graph v1.0 端点获取访问令牌和 Microsoft Graph 客户端var delegateAuthProvider = await GetAuthProvider();//初始化GraphServiceClientgraphClient = new GraphServiceClient(graphAPIEndpoint, delegateAuthProvider);返回图客户端;}私有静态异步任务GetAuthProvider(){AuthenticationContext authenticationContext = new AuthenticationContext(authority);ClientCredential clientCred = new ClientCredential(clientId, clientSecret);//ADAL 包含内存缓存,因此如果缓存令牌过期,此调用只会向服务器发送消息.AuthenticationResult authenticationResult = await authenticationContext.AcquireTokenAsync(graphResource, clientCred).ConfigureAwait(false);var token = authenticationResult.AccessToken;var delegateAuthProvider = new DelegateAuthenticationProvider((requestMessage) =>{requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", token.ToString());返回 Task.FromResult(0);});返回delegateAuthProvider;}

现在每当我开始访问我的 api 时,groupshandler.cs 都会出现异常

Microsoft.Graph.ServiceException:代码:Authorization_RequestDenied消息:权限不足,无法完成操作.

我在 azure AD 中为我的应用添加了 Microsoft 图形权限.我想阅读我们需要管理员同意的组.我在这里挣扎.我可以在用户同意选项卡下的 azure 广告中的企业应用程序下看到以下权限.

下面是通过 authenticationContext.AcquireTokenAsync 方法生成的令牌格式

另一方面,这个令牌对我来说也很奇怪,而且缺少很多字段.

现在有人请帮助我在上面的实现中做了哪些错误的步骤.有人可以在这方面提供帮助.任何帮助都会对我很有帮助.非常感谢

解决方案

您使用的是

添加应用权限后,您还需要授予管理员同意.

Net core Web API project. I registered app in azure AD for Web API app. I configured swagger and I registered one more app in Azure AD. I am trying to do authorization on my webapis based on groups. In appsettings.json I have all the values.

Below is my startup looks like.

public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            services
               .AddAuthentication(o =>
               {
                   o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;

               })
               .AddJwtBearer(o =>
               {
                   o.Authority = azureActiveDirectoryOptions.Authority;

                   o.TokenValidationParameters = new TokenValidationParameters
                   {

                       ValidAudiences = new List<string>
                       {
                          azureActiveDirectoryOptions.AppIdUri,
                          azureActiveDirectoryOptions.ClientId
                       },
                       ValidateIssuer = true
                   };
               });
            services.AddScoped<IAuthorizationHandler, GroupsCheckHandler>();
            services.AddAuthorization(options =>
            {   
                options.AddPolicy("GroupsCheck", policy =>
                {
                    policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
                    policy.RequireAuthenticatedUser();
                    policy.Requirements.Add(new GroupsCheckRequirement("2a39995a-8fd1-410e-99e2-11cf6046090d"));
                });
            });
            services.AddMvc(options =>
            {

                var policy = new AuthorizationPolicyBuilder()
                    .RequireAuthenticatedUser()
                    .Build();
                options.Filters.Add(new AuthorizeFilter(policy));
            })
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });

                c.AddSecurityDefinition("oauth2", new OAuth2Scheme
                {
                    Type = "oauth2",
                    Flow = "implicit",
                    AuthorizationUrl = swaggerUIOptions.AuthorizationUrl,
                    TokenUrl = swaggerUIOptions.TokenUrl
                });
                c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>
                {
                        { "oauth2", new[] { "readAccess", "writeAccess" } }
                });
            });
        }


        // 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();
            }
            else
            {
                app.UseHsts();
            }
            app.UseHttpsRedirection();

            app.UseSwagger();
            app.UseSwaggerUI(c =>
            {

                c.OAuthClientId(swaggerUIOptions.ClientId);
                c.OAuthClientSecret(swaggerUIOptions.ClientSecret);
                c.OAuthRealm(azureActiveDirectoryOptions.ClientId);
                c.OAuthAppName("Swagger");
                c.OAuthAdditionalQueryStringParams(new { resource = azureActiveDirectoryOptions.ClientId });
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
            });
            app.UseAuthentication();
            app.UseMvc();
        }

When I run the application using https://localhost:44319/swagger

Now I have Authorize button in my swagger. Whenever I try to Authorize, It will ask me to enter user name and password. Authentication works as expected. Next I want to hit /api/values/users/{id}. the controller looks below.

    [Authorize(Policy = "GroupsCheck")]
    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {

    }

I need group based authorization. In startup I have added policy.

services.AddAuthorization(options =>
            {   
                options.AddPolicy("GroupsCheck", policy =>
                {
                    policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
                    policy.RequireAuthenticatedUser();
                    policy.Requirements.Add(new GroupsCheckRequirement("2a39995a-8fd1-410e-99e2-11cf6046090d"));
                });
            });

Below is my GroupsCheckHandler.cs

 protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                                  GroupsCheckRequirement requirement)
        {

                GraphServiceClient client = await MicrosoftGraphClient.GetGraphServiceClient();
                //Tried to get user and dint work for me
                var user = await client.Me.Request().GetAsync(); 
                //Here exception occurs
                var groupList = await client.Groups.Request().GetAsync();


                var result = false;
                foreach (var group in groupList)
                {
                    if (requirement.groups.Equals(group.Id))
                    {
                        result = true;
                    }
                }

                if (result)
                {
                    context.Succeed(requirement);
                }
        }

Below is my MicrosoftGraphClient.cs

public static async Task<GraphServiceClient> GetGraphServiceClient()
        {
            // Get Access Token and Microsoft Graph Client using access token and microsoft graph v1.0 endpoint
            var delegateAuthProvider = await GetAuthProvider();
            // Initializing the GraphServiceClient
            graphClient = new GraphServiceClient(graphAPIEndpoint, delegateAuthProvider);

            return graphClient;
        }


        private static async Task<IAuthenticationProvider> GetAuthProvider()
        {
            AuthenticationContext authenticationContext = new AuthenticationContext(authority);
            ClientCredential clientCred = new ClientCredential(clientId, clientSecret);

            // ADAL includes an in memory cache, so this call will only send a message to the server if the cached token is expired.
            AuthenticationResult authenticationResult = await authenticationContext.AcquireTokenAsync(graphResource, clientCred).ConfigureAwait(false);
            var token = authenticationResult.AccessToken;

            var delegateAuthProvider = new DelegateAuthenticationProvider((requestMessage) =>
            {
                requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", token.ToString());
                return Task.FromResult(0);
            });

            return delegateAuthProvider;
        }

Now Whenever I start hitting to my api am getting exception in groupshandler.cs

Microsoft.Graph.ServiceException: Code: Authorization_RequestDenied
Message: Insufficient privileges to complete the operation.

I have added Microsoft graph permission to my app in azure AD. I thing to read groups we need Admin consent. Here I am struggling. Below permission I can see under enterprise application in azure ad under user consent tab.

Below is token format generated through authenticationContext.AcquireTokenAsync method

Other side this token also looks strange to me and this is missing many fields.

Now someone please help me what wrong steps I have done in the above implementation. Can someone help in this regard. Any help would be very helpful for me. Thanks a lot

解决方案

You were using client credential to get the access Token. So you need to add application permissions(not delegated permissions) on Azure portal.

After adding the application permissions, you also need to grant admin consent.

这篇关于.Net core 应用程序无法从 Microsoft Graph API 获取用户详细信息?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆