How to Update a Claim in ASP.NET Identity

How to update a claim in ASP.NET Identity?

I created a Extension method to Add/Update/Read Claims based on a given ClaimsIdentity

namespace Foobar.Common.Extensions
{
public static class Extensions
{
public static void AddUpdateClaim(this IPrincipal currentPrincipal, string key, string value)
{
var identity = currentPrincipal.Identity as ClaimsIdentity;
if (identity == null)
return;

// check for existing claim and remove it
var existingClaim = identity.FindFirst(key);
if (existingClaim != null)
identity.RemoveClaim(existingClaim);

// add new claim
identity.AddClaim(new Claim(key, value));
var authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
authenticationManager.AuthenticationResponseGrant = new AuthenticationResponseGrant(new ClaimsPrincipal(identity), new AuthenticationProperties() { IsPersistent = true });
}

public static string GetClaimValue(this IPrincipal currentPrincipal, string key)
{
var identity = currentPrincipal.Identity as ClaimsIdentity;
if (identity == null)
return null;

var claim = identity.Claims.FirstOrDefault(c => c.Type == key);

// ?. prevents a exception if claim is null.
return claim?.Value;
}
}
}

and then to use it

using Foobar.Common.Extensions;

namespace Foobar.Web.Main.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
// add/updating claims
User.AddUpdateClaim("key1", "value1");
User.AddUpdateClaim("key2", "value2");
User.AddUpdateClaim("key3", "value3");
}

public ActionResult Details()
{
// reading a claim
var key2 = User.GetClaimValue("key2");
}
}
}

Update Claims values in ASP.NET One Core

I have to SignOutAsync and SignInAsync again in order to update the
cookie?

Answer is yes.

Easiest way is you can manually sign-out and sign-in (create claims again) inside the same action method where you are updating the email.

The best solution is to save this into a classic session?

I suggest not to do that. Using session state explicitly is a bad practice in ASP.Net MVC.

How can I add/update a claim in .NET Core 3.1 after I've already authenticated?

The answer from refers when to you authenticate and get the claims from an OAUTH server. We don't know if you are using local identity tables, or OAUTH, but in any case.

  1. Define your own UserClaimsPrincipalFactory class implementation
  2. Register as a services in startup ConfigureServices
  3. Invoke the GenerateClaimsAsync method when the user select the Business type.

I include some old code (finally we implemented in another way), but maybe can help you.

  1. Define you own UserClaimsPrincipalFactory. For this, I have customized the User class, and add a new factory
    using System;
using System.ComponentModel.DataAnnotations.Schema;
using System.Security.Claims;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;

namespace Common.Models.Identity {
public class User : IdentityUser<int> {


public bool SendAlertByEmail { get; set; }
public int ClientId { get; set; } = Client.DefaultClientId;
[JsonIgnore, ForeignKey("ClientId")]
public virtual Client Client { get; set; } = null!;
}

public class ApplicationUserClaimsPrincipalFactory : UserClaimsPrincipalFactory<User> {
public ApplicationUserClaimsPrincipalFactory(
UserManager<User> userManager,
IOptions<IdentityOptions> optionsAccessor)
: base(userManager, optionsAccessor) {
}

protected override async Task<ClaimsIdentity> GenerateClaimsAsync(User user) {
ClaimsIdentity identity;

identity = await base.GenerateClaimsAsync(user);
identity.AddClaim(new Claim("ClientId", user.ClientId.ToString()));
identity.AddClaim(new Claim("ClientDescription", user.Client.Description));
return identity;
}
}
}

  1. In your ConfigureServices, configure this

     #region Configure identity
    services
    .AddDefaultIdentity<User>(
    options => {
    options.SignIn.RequireConfirmedAccount = true;
    options.Stores.MaxLengthForKeys = 256; // Max length for key. Regenerate migration if change this
    })
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultUI()
    .AddDefaultTokenProviders()
    .AddClaimsPrincipalFactory<ApplicationUserClaimsPrincipalFactory>();

    services.Configure<IdentityOptions>(options => {
    // Password settings.
    options.Password.RequireDigit = true;
    options.Password.RequireLowercase = true;
    options.Password.RequireNonAlphanumeric = true;
    options.Password.RequireUppercase = true;
    options.Password.RequiredLength = 6;
    options.Password.RequiredUniqueChars = 1;

    // Lockout settings.
    options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
    options.Lockout.MaxFailedAccessAttempts = 5;
    options.Lockout.AllowedForNewUsers = true;

    // User settings.
    options.User.AllowedUserNameCharacters =
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
    options.User.RequireUniqueEmail = false;
    });

    services.ConfigureApplicationCookie(options => {
    // Cookie settings
    options.Cookie.HttpOnly = true;
    options.ExpireTimeSpan = TimeSpan.FromMinutes(5);

    options.LoginPath = "/Identity/Account/Login";
    options.AccessDeniedPath = "/Identity/Account/AccessDenied";
    options.SlidingExpiration = true;
    });
    #endregion Configure identity
  2. Use IoC to pass your ApplicationUserClaimsPrincipalFactory to your "Select business/client" request, and use it for add the claim

User claim update not effected in ASP.NET Identity?

The problem is that the claims are used in the authentication process and are part of the authentication token/cookie. If you want to remove a claim from the current user then you need to make sure the client get a new token/cookie.

If you're running for example bearer tokens with your api then you need to generate a new token and return that token to the client from your UpdateUserGroup(). The client then need to use the new token the next time it makes a request to the api.



Related Topics



Leave a reply



Submit