C# 如何持久化用户';索赔清单?

C# 如何持久化用户';索赔清单?,c#,.net-core,openid-connect,claims,C#,.net Core,Openid Connect,Claims,我正在构建一个ASP.NET核心(v3.1)模块,我刚刚配置了一个OpenIdConnect身份验证。现在,我需要从API获取所有用户角色,以便授予或拒绝对它们的访问,然后我通过类似以下事件的OnAuthorizationCodeReceived向用户声明列表中的同一声明角色“ClaimTypes.role”添加了多个声明值: OnAuthorizationCodeReceived = async (context) => { // Uses the authentication

我正在构建一个ASP.NET核心(v3.1)模块,我刚刚配置了一个OpenIdConnect身份验证。现在,我需要从API获取所有用户角色,以便授予或拒绝对它们的访问,然后我通过类似以下事件的
OnAuthorizationCodeReceived
向用户声明列表中的同一声明角色“ClaimTypes.role”添加了多个声明值:

OnAuthorizationCodeReceived = async (context) =>
{
    // Uses the authentication code and gets the access and refresh token
    var client = new HttpClient();
    var response = await client.RequestAuthorizationCodeTokenAsync(new AuthorizationCodeTokenRequest()
    {
        Address = urlServer + "/connect/token",
        ClientId = "hybrid",

        Code = context.TokenEndpointRequest.Code,
        RedirectUri = context.TokenEndpointRequest.RedirectUri,
    }

    if (response.IsError) throw new Exception(response.Error);

    var identity = new ClaimsIdentity(context.Principal.Identity);

    var listRoles = GenericProxies.RestGet<List<string>>(urlGetRoles, response.AccessToken); // GET request to API
    listRoles.ForEach(role => identity.AddClaim(new Claim(ClaimTypes.Role, role)));

    context.HttpContext.User = new ClaimsPrincipal(identity);

    context.HandleCodeRedemption(response.AccessToken, response.IdentityToken);
}
但是,很显然,在我的主控制器(即用户在经过身份验证后被重定向到的地方)中,当我访问HttpContext.user时,除了“Admin”(我猜这是默认的ClaimTypes.Role值)之外,我似乎找不到以前添加的任何角色

在阅读其他一些帖子、论坛和主题时,我发现这可能是一个上下文持久性问题,我试图在我的帐户控制器中使用以下代码来解决这个问题:

public async Task Login(string returnUrl = "/")
{
    await HttpContext.ChallengeAsync(
        "OIDC",
        new AuthenticationProperties
        {
            AllowRefresh = false,
            IsPersistent = true,
            RedirectUri = returnUrl
        });
}
一些例子说我可以使用
context.Principal.AddIdentity(identity)以保留新的索赔列表,但随后出现以下错误:

InvalidOperationException: only a single identity supported
IdentityServer4.Hosting.IdentityServerAuthenticationService.AssertRequiredClaims(ClaimsPrincipal principal)

总而言之,我必须找到一种方法来保存我添加到用户声明列表中的角色声明,但直到现在我都没有成功。

如果这对任何人都有用,请更新

我推断
context.HttpContext.User=newclaimsprincipal(identity)的问题是什么,我以前理解它是处理新声明持久性的代码的一部分

实际上,我注意到有一个
上下文。Principal
类型的
ClaimsPrincipal
属性的Principal
属性,看起来像是实际的当前上下文,所以我深入研究了它,并试图找到一种方法,将元素添加到其只读的“
IEnumerable Claims
”属性中

过了一段时间,我发现以下解决方案对我很有效:

而不是

var identity = new ClaimsIdentity(context.Principal.Identity);
var listRoles = GenericProxies.RestGet<List<string>>(urlGetRoles, response.AccessToken); // GET request to API
listRoles.ForEach(role => identity.AddClaim(new Claim(ClaimTypes.Role, role)));
var identity=newclaimsidentity(context.Principal.identity);
var listRoles=GenericProxies.RestGet(urlGetRoles,response.AccessToken);//获取对API的请求
listRoles.ForEach(role=>identity.AddClaim(新声明(ClaimTypes.role,role));
我试过了

var identity = context.Principal.Identity as ClaimsIdentity;
if(identity != null)
{
    var listRoles = GenericProxies.RestGet<List<string>>(urlGetRoles, response.AccessToken); // GET request to API 
    foreach (var role in listRoles)
    {
        identity.AddClaim(new Claim(ClaimTypes.Role, role));
    }
}
var identity=context.Principal.identity作为索赔实体;
如果(标识!=null)
{
var listRoles=GenericProxies.RestGet(urlGetRoles,response.AccessToken);//获取对API的请求
foreach(listRoles中的var角色)
{
identity.AddClaim(新声明(ClaimTypes.Role,Role));
}
}
var identity = new ClaimsIdentity(context.Principal.Identity);
var listRoles = GenericProxies.RestGet<List<string>>(urlGetRoles, response.AccessToken); // GET request to API
listRoles.ForEach(role => identity.AddClaim(new Claim(ClaimTypes.Role, role)));
var identity = context.Principal.Identity as ClaimsIdentity;
if(identity != null)
{
    var listRoles = GenericProxies.RestGet<List<string>>(urlGetRoles, response.AccessToken); // GET request to API 
    foreach (var role in listRoles)
    {
        identity.AddClaim(new Claim(ClaimTypes.Role, role));
    }
}