【问题标题】:.Net core App unable to get user details from Microsoft Graph API?.Net 核心应用程序无法从 Microsoft Graph API 获取用户详细信息?
【发布时间】:2020-01-13 10:00:59
【问题描述】:

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

下面是我的启动的样子。

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

当我使用https://localhost:44319/swagger 运行应用程序时

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

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

    }

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

services.AddAuthorization(options =>
            {   
                options.AddPolicy("GroupsCheck", policy =>
                {
                    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 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);
                }
        }

下面是我的 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;
        }

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

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

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

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

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

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

【问题讨论】:

    标签: azure .net-core azure-active-directory authorization


    【解决方案1】:

    您使用client credential 获取访问令牌。所以你需要在 Azure 门户上添加应用程序权限(不是委派权限)。

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

    【讨论】:

    • 谢谢。我的应用程序需要访问图形 api,所以我需要授予应用程序权限并授予管理员同意权?此外,我的令牌看起来与普通令牌不同,并且缺少几个字段。请问这是什么原因造成的
    • @Niranjan 是的,你是对的。如果您添加了应用程序权限,它们将在访问令牌中返回。
    • 好的,谢谢 在上面的代码中,每当我尝试使用 authenticationContext.AcquireTokenAsync 获取访问令牌时,我是否还需要在请求中传递范围?
    • @Niranjan 您正在使用 adal。范围参数不是必需的。
    • 所以我使用的是 v1。只有 v2 才需要范围,对吗?
    猜你喜欢
    • 2023-01-12
    • 1970-01-01
    • 2015-07-19
    • 2020-05-09
    • 1970-01-01
    • 1970-01-01
    • 2014-01-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多