Invalidate ClaimsPrincipal after it has been modified
Asked Answered
B

1

0

I am using ASP.NET MVC, Identity2.

I have added "FirstName" Custom ClaimPrincipal:

public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser, long> manager)
{
    var userIdentity = await manager.CreateIdentityAsync(
                           this,
                           DefaultAuthenticationTypes.ApplicationCookie);

    // Add custom user claims here
    userIdentity.AddClaim(new Claim("FirstName", FirstName));

    return userIdentity;
}

If I update the value of "FirstName", I need to logout and log back in, for the "FirstName" Claim to be updated. Is it possible to invalidate "FirstName" Claim, so it's value is forced to be refreshed?


I have seen this question, which shows how to update the value of Claims, I was wondering if there is easier way to just invalidate them.

Botanomancy answered 13/2, 2019 at 5:56 Comment(3)
The technical solution depends on your setup. If you are storing the information in a cookie then you'll need to update the cookie. If you are using access tokens then you'll need to wait until it expires or replace it with a new access token, e.g. using a refresh token. The logical solution is to not include claims that change often or can be determined in another way. You could setup a UserInfo endpoint where you can request the current FirstName and other info about the user. But you can also make it part of the business context, like asking what the first name is.Tangled
Thanks @RuardvanElburg for your explanation. I am using Cookie, the reason I am storing FirstName and LastName as Claim is that I want them to be stored in the Cookie... I thought reading them from cookie would be faster than reading the user object from the DB. FirstName and LastName don't change very often... do you think, keeping them as Claim, is a sensible solution?Botanomancy
It always depends on your design, but sure. It's fine to have claims like FirstName, LastName. Especially when you want to show them on each page. It may be faster, but I doubt that you can actually measure the difference. There are also other ways to increase performance, like caching.Tangled
B
3

When looking at MS built-in template, I noticed that they alway makes a call to SignInManager.SignInAsync, after changing user credentials (e.g. password, 2 Factor Authentication, etc).

I also noticed that the Claims are updated once the user logs out and logs back in... so after changing "FirstName" which is stored in a Claim, I called SignInManager.SignInAsync to re-signin the User... this way, the Claims are updated:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> UpdateFirstName(string firstName)
{
    var user = await UserManager.FindByIdAsync(User.Identity.GetUserId<long>());
    user.FirstName = firstName;

    // update FirstName which is stored in a Claim
    var result = await UserManager.UpdateAsync(user);

    if (result.Succeeded)
    {
        // re-signin the user, to refresh the Claims
        await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);

        // you need to redirect after calling SignInAsync, so claims are refreshed
        return RedirectToAction("Index"); 
    }

    // add some error message...
    return View();
}

Note: As shown in the question, I am storing the Claims in Cookie.

Botanomancy answered 14/2, 2019 at 1:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.