asp.net-coreclaimsasp.net-authorization

Asp.Net Core Mvc6 Claims Authorization is not persistent


I am doing an Asp.Net Core Mvc 6 App where I dynamically assign Claims to the user.

I have in the database all Roles that a user must have to access specific fields of the page.

I also have the role of the user.

I am creating Claims where the user's role matches the field page User role. And then I create a ClaimsPrincipal with those list of Roles.

This are the data in the database

data

This is how I create the permission for the user..

 private string[] TransformRowsIntoPermissions(List<RolesAccessModel>? rows, string userRole)
        {
             List<string> permissionList = new();
            if(rows!=null)
            { 
                foreach (RolesAccessModel row in rows)
                {
                    if (row.Roles!=string.Empty && row.Roles != null && !row.Roles.Contains(userRole))
                        continue;

                       // if we get here we have a match
                       if (!permissionList.Contains(row.EventName))
                        permissionList.Add(row.EventName);
                }
            }

            return permissionList.ToArray(); 
        }

When I have the Permission List, I add it as Claims

  private Claim[] CreateClaimsFromArray(string[] permissions)
        {
            List<Claim> claims = new();
            foreach (var permission in permissions)
                claims.Add(new Claim(permission, "-"));

            return claims.ToArray();
        }

And in the main function I save it as ClaimPrincipal

   private async void CreateClaimsByUserRole(string role)
        {
            ClaimsIdentity claimsIdentity =await _iUIConfig.CreateClaimsByUserRole(role);
            var userPrincipal = new ClaimsPrincipal(new[] { claimsIdentity });
            _ = HttpContext.SignInAsync(userPrincipal);
        } 

I do not know if line _ = HttpContext.SignInAsync(userPrincipal); is necessary.

I checked userPrincipal and it has all the data.

Claims

What I need to do is to ask in the View for that claims in order to show or to not Show the fields. But when I ask if it is null...

 @{
    var claimsIdentity = User.Identity as System.Security.Claims.ClaimsIdentity;
    if (claimsIdentity != null)
     {
       var c = claimsIdentity.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier);

       if (c != null)
       {
         <p>
                @c.Type.ToString();
                @c.Value.ToString();
          </p>
        }
        else
        {
          <p>
              null
          </p>
        }
     }
 }

It is null

If I ask for a specific value

@{ 
          if(System.Security.Claims.ClaimsPrincipal.Current.Claims.ToList().FirstOrDefault(c => c.Type == "DocumentId" && c.Value == "-") != null)
 {
                       .....
  }

} Got an error System.NullReferenceException: 'Object reference not set to an instance of an object.'

Even If a call a Controller/Method and ask for

 var identity = (ClaimsPrincipal)Thread.CurrentPrincipal;

Is null..

I have to do it persistent for all the App.

I am not using Authentication because it is not implemented yet.. I am using SSO from another system. For that reason, for my understanding Cookie are used for Authentication.

In program.cs I only have

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("AdminAccess", policy => policy.RequireRole("Admin"));

    options.AddPolicy("ManagerAccess", policy =>
        policy.RequireAssertion(context =>
                    context.User.IsInRole("Admin")
                    || context.User.IsInRole("Manager")));

    options.AddPolicy("UserAccess", policy =>
        policy.RequireAssertion(context =>
                    context.User.IsInRole("Admin")
                    || context.User.IsInRole("Manager")
                    || context.User.IsInRole("User")));
});

and

app.UseAuthorization();

What am I missing to do it persistent?

Thanks


Solution

  • ClaimsPrincipal.Current was used in asp.net,however,in Asp.net core it is no longer set

    To retrieve the current user in an ASP.NET Core MVC app,you could try with ControllerBase.User orHttpContext.User

    You could check this document for more details

    SignInAsync creates an encrypted cookie and adds it to the current response.You could get the claims after authenticating successfully in the following request untill the cookie expires(not the current request)

    Notice HttpContext.User could be setted directly

    And in View you could get the claims in @ section as below:

    @{
        var claims = this.ViewContext.HttpContext.User.Claims.ToList();
    }