gpt4 book ai didi

c# - 授权策略始终返回 403(禁止)-MVC/API

转载 作者:行者123 更新时间:2023-12-01 08:23:44 28 4
gpt4 key购买 nike

我创建了一个 API(带有 EF Core 的 .Net Core 2),其端点用于检索某些角色。我将 ASPNetIdentity 集成到我的项目中,并使用 AspNetRoles 和 AspNetRoleClaims。

在我的例子中,调用 API 时,用户具有特定角色(管理员)。这个角色有一些角色要求。在startup.cs中,我添加了该角色的策略:

   options.AddPolicy(
"Create Roles", policy => policy.RequireClaim("Can create roles", "role.create"));
options.AddPolicy(
"View Roles", policy => policy.RequireClaim("Can read roles", "role.read"));
options.AddPolicy(
"Edit Roles", policy => policy.RequireClaim("Can update roles", "role.update"));
options.AddPolicy(
"Delete Roles", policy => policy.RequireClaim("Can delete roles", "role.delete"));

在我的前端中,用户可以使用他们的 Microsoft (azure) 帐户登录,并且他们的 oidc 声明 (ID) 与 AspNetUser 表中的 ID 匹配,如果在用户表中找不到他们的 oidc,则会自动添加他们(及其oidc id 作为 aspnetuser id),并且他们获得默认角色。

但是,当调用角色端点时,它总是返回 403 错误(禁止)。当我检查表时,用户具有访问端点的正确角色和角色声明。怎么可能一直返回403?

端点如下所示:

[HttpGet]
[Authorize(Policy = "View Roles")]
public IEnumerable<IdentityRole> GetRole()
{
return _context.Roles;
}
经过一番研究,我发现一篇文章告诉您需要在发送到 API 的 token 中包含用户的角色(声明),但这意味着我需要一个首先返回用户的角色,前端需要拾取它并将其添加到 token 中,然后使用 token 中包含的角色调用所有其他端点?或者我在这里走错了路?

----更新----

我 90% 确定策略/授权检查需要将角色声明包含在用户的 token 中。然而,现在的流程如下:

  1. 用户转到前端项目(react frontend)。
  2. 前端使用 adal.js 检查用户是否已通过身份验证,如果未通过身份验证,则用户将被重定向到 Microsoft 登录页面。
  3. 登录成功后,正在调用API。
  4. 在 API 的 DI (AddJwtBearer) 中,将 oid 声明与 AspNetUsers 表的 ID 进行比较,如果不存在,则使用 oid 值作为 AspNetUsers 表的 ID 将用户添加到 AspNetUser 表中AspNetUser。

现在用户也已添加到 AspNetUser 表中,我可以使用 Asp.Net Identity 通过 Roles 和 RoleClaims 进行授权。

然而,问题是 API 最初收到的 token 是 Azure token ,它对我的​​身份表一无所知(如果我错了,请纠正我)。我相信这也是我的政策不起作用的原因(如果我错了,请再次纠正我)。

我发现一个帖子,问题或多或少是相同的( https://joonasw.net/view/adding-custom-claims-aspnet-core-2 ),技巧是使用我需要的身份声明(例如 ClaimTypes.Role)扩展当前 token 。

我实现此目的的代码如下:

// Add authentication (Azure AD)
services
.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
sharedOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; // Use JWT as ChallendgeSchema, if not, ASPNet Identity will be used by default and this will return a default non-existing endpoint (because it is not created): Account/Login; https://stackoverflow.com/questions/45878166/asp-net-core-2-0-disable-automatic-challenge
})
.AddJwtBearer(options =>
{
options.Audience = this.Configuration["AzureAd:ClientId"];
options.Authority = $"{this.Configuration["AzureAd:Instance"]}{this.Configuration["AzureAd:TenantId"]}";

// Added events which checks if the user (token user) exists in our own database, if not then the user is being added with a 'User' role
options.Events = new JwtBearerEvents()
{
OnTokenValidated = context =>
{
// Check if roles are present
CheckRoles cr = new CheckRoles();
cr.CreateRoles(services.BuildServiceProvider());

// Check if the user has an OID claim(oid = object id = user id)
if (!context.Principal.HasClaim(c => c.Type == "http://schemas.microsoft.com/identity/claims/objectidentifier"))
{
context.Fail($"The claim 'oid' is not present in the token.");
}

ClaimsPrincipal userPrincipal = context.Principal;

CheckUser cu = new CheckUser();

cu.CreateUser(userPrincipal, services.BuildServiceProvider());

// Extend the current token with my (test) Role claim
var claims = new List<Claim>
{
new Claim(ClaimTypes.Role, "Admin")
};
var appIdentity = new ClaimsIdentity(claims);
context.Principal.AddIdentity(appIdentity);


return Task.CompletedTask;
}
};
});

遗憾的是,上面的方法不起作用,当从前端调用 API 时, token 保持不变,并且没有添加 RoleClaim。任何人都知道如何将我的 RoleClaim 添加到 token ,以便我可以使用我的策略?

最佳答案

When calling the API the user has a specific role (Admin) in my case. This role has a few role claims.

如果用户在主体对象中将 role.read 作为 ClaimTypes.Role,您可以在 Startup.cs 中创建如下所示的策略> -

public void ConfigureServices(IServiceCollection services)
{
...
services.AddAuthorization(options =>
{
options.AddPolicy("View Roles", policyBuilder =>
{
policyBuilder.RequireAuthenticatedUser()
.RequireAssertion(context =>
context.User.HasClaim(ClaimTypes.Role, "role.read"))
.Build();
});
});
...
}

更新

您需要将 JwtBearerDefaults.AuthenticationScheme 身份验证类型添加到声明身份,以便它与默认方案匹配。

services
.AddAuthentication(sharedOptions =>
{
...
})
.AddJwtBearer(options =>
{
...
options.Events = new JwtBearerEvents()
{
OnTokenValidated = context =>
{
...
var appIdentity = new ClaimsIdentity(claims,
JwtBearerDefaults.AuthenticationScheme);
^^^^^

context.Principal.AddIdentity(appIdentity);

return Task.CompletedTask;
}
};
});

关于c# - 授权策略始终返回 403(禁止)-MVC/API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50329756/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com