. Net ядро ​​приложение не может получить информацию о пользователе из Microsoft Graph API? - PullRequest
1 голос
/ 13 января 2020

Net основной проект веб-API. Я зарегистрировал приложение в azure AD для приложения Web API. Я настроил swagger и зарегистрировал еще одно приложение в Azure AD. Я пытаюсь сделать авторизацию на моем веб-сайте по группам. В 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 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;
        }

Now При каждом запуске при попытке получить доступ к моему API получаю исключение в groupshandler.cs

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

Я добавил разрешение графика Microsoft в свое приложение в azure AD. Мне нравится читать группы, нам нужно согласие администратора. Здесь я борюсь. Ниже разрешения я вижу в приложении для предприятий в azure объявлении на вкладке согласия пользователя.

Enterprise Apps in Azure AD

Ниже представлен формат токена, созданный с помощью authenticationContext.AcquireTokenAsyn c method

JWT token Другая сторона, этот токен также выглядит странно для меня, и в нем пропущено много полей.

Теперь кто-то, пожалуйста, помогите мне, какие неправильные шаги я сделал в приведенной выше реализации. Может ли кто-то помочь в этом отношении. Любая помощь будет очень полезна для меня. Большое спасибо

1 Ответ

1 голос
/ 14 января 2020

Вы использовали учетные данные клиента для получения токена доступа. Таким образом, вам необходимо добавить разрешения приложения (не делегированные разрешения) на портале Azure.

enter image description here

После добавления разрешений приложения также необходимо предоставить согласие администратора.

...