liveBook · Manning

ClaimsPrincipal

As explained in ASP.NET Core in Action, 3e

ClaimsPrincipal is a .NET security object that represents an authenticated user through a collection of claims and identities.

ClaimsPrincipal represents the current user of an ASP.NET Core request. Find it at HttpContext.User when you need to know who made a request or inspect information about them. A principal holds claims: individual pieces of information with a type and an optional value, such as a name or email address. section 23.1.1

Every request starts with a principal. Without authentication, it is anonymous, unauthenticated, and has no claims. Signing in replaces it with a principal for the authenticated user; authentication can then restore that principal on later requests. section 23.1.1 section 23.1.2

In a traditional ASP.NET Core app, the path from sign-in to a later request looks like this:

  • The app checks the submitted identifier and secret, such as an email address and password. section 23.1.2
  • After a successful sign-in, SignInManager sets HttpContext.User and stores an encrypted version of the principal in a cookie. section 23.1.2
  • On a later request, the cookie is validated and its principal is used to authenticate the request. section 23.1.2

Do not confuse the principal with an IdentityUser database entity. At sign-in, Identity loads the entity and combines it with stored user claims to create the ClaimsPrincipal. The principal—not the entity—is used for authentication and serialized to the cookie. In a minimal API handler, you can request ClaimsPrincipal directly as a parameter instead of navigating through HttpContext.User. section 23.3.3 section 7.6.1

Add and read a friendly name

When a user registers, create a FullName claim from the submitted name and add it with UserManager.AddClaimAsync. A Razor Page or template can then read it with User.FindFirstValue("FullName"). Claims can also represent permission-related information, such as IsAdmin; decide who should receive such a claim rather than treating a submitted value as permission. section 23.6 section 23.1.1

Listing 23.7 Adding a custom claim to a new user in the Register.cshtml.cs page
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    if (ModelState.IsValid)
    {
        var user = new ApplicationUser {                        #1
            UserName = Input.Email, Email = Input.Email };      #1
        var result = await _userManager.CreateAsync(            #2
            user, Input.Password);                              #2
        if (result.Succeeded)
        {
            var claim = new Claim("FullName", Input.Name);      #3
            await _userManager.AddClaimAsync(user, claim);      #4
            var code = await _userManager                       #5
                .GenerateEmailConfirmationTokenAsync(user);     #5
            await _emailSender.SendEmailAsync(                  #5
                 Input.Email, "Confirm your email", code );     #5
            await _signInManager.SignInAsync(user);             #6
            return LocalRedirect(returnUrl);
        }
        foreach (var error in result.Errors)                    #7
        {                                                       #7
            ModelState.AddModelError(                           #7
                string.Empty, error.Description);               #7
        }                                                       #7
    }                                                           #7
       return Page();                                           #7
}
#1 Creates an instance of the ApplicationUser entity
#2 Validates that the provided password meets requirements, and creates the user in the database
#3 Creates a claim, with a string name of “FullName” and the provided value
#4 Adds the new claim to the ApplicationUser’s collection
#5 Sends a confirmation email to the user, if you have configured the email sender
#6 Signs the user in by setting the HttpContext.User; the principal will include the custom claim
#7 There was a problem creating the user. Adds the errors to the ModelState and redisplays the page.

The registration listing shows a Claim being created and added to the new user through UserManager. section 23.6

Claims can describe a person or support authorization decisions. Authentication establishes who the user is; authorization determines what they may do. Roles remain compatible for older applications, but claims are generally preferred for new ones. If users need to edit a property, adding it to IdentityUser may be more convenient, though that approach requires a database change. section 23.7 section 23.6

How ASP.NET Core in Action, 3e covers it

How deep it goes
Defines principals and claims, then traces sign-in, cookie restoration, and custom-claim use without detailing ClaimsPrincipal internals.
Examples
Uses an anonymous request, email-and-password sign-in, and a FullName claim added during registration and read in a Razor template.
What it assumes
Introduces principals and claims from their definitions while placing them in an ASP.NET Core request and sign-in flow.
What you can do after
Apply it via ASP.NET Core Identity to add a user claim and read it from the current principal.
How it connects
Connects HttpContext.User, claims, ASP.NET Core Identity, authentication cookies, and authorization.

Also explained in

Compare how 2 books explain ClaimsPrincipal →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of ASP.NET Core in Action, 3e. The section links point to the parts of the book it draws on.