0
votes

I have a Blazor application using scaffolded Identity pages. Out of the box, the userid is shown by the LoginDisplay.razor componet. This component calls

 @context.User.Identity.Name

to dispay the current userid (not the natural name). So in order to display the natural name, I used this guide to first make changes in the default Identity schema: https://docs.microsoft.com/en-us/aspnet/core/security/authentication/add-user-data?view=aspnetcore-3.1&tabs=visual-studio#test-create-view-download-delete-custom-user-data because Blazor scaffolded identity uses razor pages. However, after doing this, I realized that there is no way to get this extra user information in a Razor component in Blazor. However, I found that Claims are available to the Razor component. So I thought of adding claims to users as they get registered. So I used the following statement to add a user claim in Register.cshtml.cs:

   await _userManager.AddClaimAsync(user, new System.Security.Claims.Claim("name", user.Name));

user.Name comes form user input.

After doing this, the interesting part is that now when I run the application, @context.User.Identity.Name is returning the natural name, not the userid.

My question is why is this so? Why does adding a 'name' claim make @context.User.Identity.Name return the natural name instead of the userid as it was doing previously?

I am using .NET5 latest preview.

Totally confused.

1
Browsing the code answers the question : github.com/dotnet/aspnetcore/blob/…agua from mars

1 Answers

0
votes
await _userManager.AddClaimAsync(user, new System.Security.Claims.Claim("name", user.Name));

It is not a good idea to do that this way, unless you know what you're doing.

Why does adding a 'name' claim make @context.User.Identity.Name return the natural name instead of the userid as it was doing previously?

`@context.User.Identity.Name` ordinarily returns the value of `UserName` column in the Users table, which by default is the user's email. This value is passed to the client in the Jwt token as a claim called "name". If you add a user 

to a claim named "name" with the value "NaturalName", the Jwt token will contain a claim called "name" with the value "NaturalName" instead of the value in the UserName column. This is exactly what your code is doing: adding the user to the "name" claim in the UserClaims table, and thus @context.User.Identity.Name returns the "NaturalName" value.

Incidentally, there is another claim named preferred_username which still retains the value of the UserName column; that is, the email value...

However, after doing this, I realized that there is no way to get this extra user information in a Razor component in Blazor.

Not true... I know about five ways to do it, depending on your requirements, and the flavor of Blazor you're using. Is it client-side or server-side ? You didn't mention this...

Is it documented anywhere that entering a 'name' claim would force context.User.Identity.Name to provide the 'name' claim instead of the userid?

Not that I know...especially not in the way you describe it. Things are much more complicated. Actually, it is documented in my answer. Documentations have no great value. You should test the software, learn how it works, etc.

Tell you what to do... Run you app without having added your user to any claim. Now authenticated, and see that your email is displayed. Press F12, navigate to the Application tab. Look for the profile section below the Key/Value table, and then look for the item name. Its value should be your email. name is the name of a claim. It is the name claim. It is passed in the Jwt token by the IdentityServer by default, and its value is taken from the UserName column if no name claim is assigned to a user. Note also that there is another claim called preferred_username whose value, alas, is the user's email.

Now assign to the user a claim called name in the AspNetUserClaims: In the ClaimType column add the string name and in the ClaimValue set the string user3656651...Save. Now once again, run your app, authenticate... @context.User.Identity.Name now displays the string user3656651, and not the user's email because IdentityServer found that your user is assigned to a name claim, and what is more natural for her than to display the natural name ;) . Do the above and you'll learn much more than any document can offer.

Note: In Program.Main method of your WebAssembly app there is this code:

builder.Services.AddApiAuthorization();

You can augment it to ;

builder.Services.AddApiAuthorization(configure => configure.UserOptions.NameClaim = "preferred_username");

Gets or sets the claim type to use for the user name.

In other words, @context.User.Identity.Name is instructed to display the value the preferred_username claim holds.

Note: The instruction is part of Blazor...the preferred_username claim is created by IdentityServer as specified by the OpenID Connect and oauth2.o specifications.

The only documentations I know about the instruction above is: Gets or sets the claim type to use for the user name. And I've found it after discovering the above option...

Anyhow, what does that mean ? That the name claim is used by default...