8

I'm using ASP.NET core identity with EF end I would like to store data related to the user in the authentication cookie.

This is how I used to do with ASP.NET 4.6 (appcontext is the data to store):

public static void IdentitySignin(AppContext appContext, string providerKey = null, bool isPersistent = false)
{
    var claims = new List<Claim>();

    // create *required* claims
    claims.Add(new Claim(ClaimTypes.NameIdentifier, appContext.UserId.ToString()));
    claims.Add(new Claim(ClaimTypes.Name, appContext.UserName));

    // serialized AppUserState object
    claims.Add(new Claim("appcontext" + EZA.Store.AppContext.Version, appContext.ToString()));

    var identity = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie);

    // add to user here!
    AuthenticationManager.SignIn(new AuthenticationProperties()
    {
        AllowRefresh = true,
        IsPersistent = isPersistent,
        ExpiresUtc = DateTime.UtcNow.AddDays(7),
    }, identity);
}

but now I'm using ASP.NET Identity with EF and I can't find a way to store some data in the cookie.

2
  • 1
    Not sure what you mean by "ASP.NET Identity with EF" - are you referring to something like this? Commented Sep 18, 2016 at 9:10
  • did u get it working mate? Commented Mar 31, 2017 at 6:38

2 Answers 2

8

Use AddClaimsAsync or AddClaimAsync of UserManager<YourUserIdentity>. for exemple like this when you sign in your user:

public class AccountController : Controller
{
    public UserManager<YourUserIdentity> UserManager { get; private set; }

    public SignInManager<YourUserIdentity> SignInManager { get; private set; }

    public AccountController(UserManager<YourUserIdentity> userManager, 
        SignInManager<YourUserIdentity> signInManager)
    {
        UserManager = userManager;
        SignInManager = signInManager;
    }

    public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
    {
        if (ModelState.IsValid)
        {
            var user = await UserManager.FindByNameAsync(model.UserName);

            await UserManager.AddClaimAsync(user, new Claim("your-claim", "your-value"));

            var signInStatus = await SignInManager.PasswordSignInAsync(user, model.Password, model.RememberMe, lockoutOnFailure: false);

            if (signInStatus.Succeeded)
                return RedirectToLocal(returnUrl);

            ModelState.AddModelError("", "Invalid username or password.");
            return View(model);
        }

        // If we got this far, something failed, redisplay form
        return View("Index", new LoginPageViewModel() { Login = model });
    }
 }
Sign up to request clarification or add additional context in comments.

6 Comments

Thank you but this saves the data in the table aspuserclaims in the database. Does it also save the data in the authentication cookie? Is there a way to save data only in the cookie and not in the table. I don't really want to invoke the database everytime I need the data, I I would like to work without sessions
yes, this store the claims in the authentication cookie if you use cookie authenication
How do you configure cookie authentication in the ConfigureServices method?
Identiy use cookie authentication by default
ok but I don't want to save data in the database but only in the cookie. How can I achieve that?
|
7

Before i read @aqua's answer(i have learned this way just now), i would say that you have two options:

1 - Overriding UserClaimsPrincipalFactory like below:

public class AppClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser, IdentityRole>
{
    public AppClaimsPrincipalFactory(
        UserManager<ApplicationUser> userManager,
        RoleManager<IdentityRole> roleManager,
        IOptions<IdentityOptions> optionsAccessor) : base(userManager, roleManager, optionsAccessor)
    {
    }

    public async override Task<ClaimsPrincipal> CreateAsync(ApplicationUser user)
    {
        var principal = await base.CreateAsync(user);

        ((ClaimsIdentity)principal.Identity).AddClaims(new[] {
             new Claim("<claim name>", value)
        });

        return principal;
    }
}

// register it
services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, AppClaimsPrincipalFactory>();

2- Using OnSigningIn event.

        services.Configure<IdentityOptions>(opt =>
        {
            opt.Cookies.ApplicationCookie.Events = new CookieAuthenticationEvents()
            {
                OnSigningIn = async (context) =>
                {
                    ClaimsIdentity identity = (ClaimsIdentity)context.Principal.Identity;
                    identity.AddClaim(new Claim("<claim name>", value));
                }
            };
        });

4 Comments

I did not know these options either
Option 2 looks interesting. Does it also store claim in database?
Been searching for hours for a way to persist a custom claim from http call to http call, tried a dozen things and none of them actually do it. I tried this, but in .NET Core 3.1, IdentityOptions has no Cookies property.
Option 2 worked for me (with .Net 6). OnSigningIn fires before the authentication cookie is created, so that claims added there are persisted. I was able to pass parameters from the Login page to the event hander via HttpContext.Items. OnSigningIn can also test for other "session" claims (not saved to the Identity store) that have previously been added.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.