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

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

问题描述

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



下面是我的创业公司。

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

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

o.TokenValidationParameters =新的TokenValidationParameters
{

ValidAudiences =新列表< 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,新信息{标题=我的API,版本= v1}) ;

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


// //运行时调用此方法。使用此方法来配置HTTP请求管道。
public void Configure(IApplicationBuilder app,IHostingEnvironment env)
{
if(env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();

应用程序。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();
}

当我使用



现在我在招摇中有授权按钮。每当我尝试授权时,它将要求我输入用户名和密码。身份验证按预期方式工作。接下来,我要点击/ api / values / users / {id}。

  [Authorize(Policy = GroupsCheck)] 
[Route( api / [控制器]]]
[ApiController]
公共类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

 受保护的覆盖异步任务HandleRequirementAsync(AuthorizationHandlerContext上下文,
GroupsCheckRequirement要求)
{

GraphServiceClient client = await MicrosoftGraphClient.GetGraphServiceClient();
//试图让用户和我的工作
var user = await client.Me.Request()。GetAsync();
//这里发生异常
var groupList = await client.Groups.Request()。GetAsync();


var result = false;
foreach(groupList中的可变组)
{
if(requirement.groups.Equals(group.Id))
{
result = true;
}
}

如果(结果)
{
context.Succeed(要求);
}
}

下面是我的MicrosoftGraphClient.cs

 公共静态异步任务< GraphServiceClient> GetGraphServiceClient()
{
//使用访问令牌和Microsoft graph v1.0端点
获取访问令牌和Microsoft Graph Client var委托AuthProvider =等待GetAuthProvider();
//初始化GraphServiceClient
graphClient = new GraphServiceClient(graphAPIEndpoint,RepresentativeAuthProvider);

return graphClient;
}


私有静态异步Task< IAuthenticationProvider> GetAuthProvider()
{
AuthenticationContext authenticationContext = new AuthenticationContext(authority);
ClientCredential clientCred =新的ClientCredential(clientId,clientSecret);

// ADAL包含一个内存中缓存,因此该调用仅在缓存的令牌过期时才向服务器发送消息。
AuthenticationResult authenticationResult =等待身份验证上下文.AcquireTokenAsync(graphResource,clientCred).ConfigureAwait(false);
var令牌= authenticationResult.AccessToken;

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

返回的委托AuthorAuthProvider;
}

现在,每当我开始使用我的api时,groupshandler.cs中都会出现异常。 / p>

  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核心应用程序无法从Microsoft Graph API获取用户详细信息?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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