UseJwtBearerAuthentication does not get User.Identity.Name populated
Solution 1
in your claims (second code snippet) I can only see this:
new Claim(ClaimTypes.NameIdentifier, applicationUser.UserName),
but you need to add this:
new Claim(ClaimTypes.Name, applicationUser.UserName),
then User.Identity.Name should contain the username.
Solution 2
Another option is to set the namespace for the JwtRegisteredClaimNames.Sub
in the tokenValidationParameters
. This will let you continue to use the standard:
var tokenValidationParameters = new TokenValidationParameters
{
// Ensure that User.Identity.Name is set correctly after login
NameClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
... existing code ...
}
Update: Diogo Barros left a comment on my blog about this topic:
"Hello,
Thank you for your help. This worked for me. For more consistency and safety, you can use the ClaimTypes.NameIdentifier (in the System.Security.Claims namespace), instead of the hardcoded string."
I've changed our code to use the built-in ClaimTypes enumeration as it is a bit more elegant than using the namespace string.
Solution 3
Adding app.UseAuthentication();
to
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
fixed my issue.
Related videos on Youtube
Afshar Mohebi
I am Afshar Mohebi, a software engineer. I have worked in many companies since 2002. In specific periods of time I have been freelancer, remote worker or company founder. My main platform has been .Net but also interested to try Linux related platforms. I love to develop software to help people in their life and business. I like projects that are following best practices of software development. Please see my English blog here
Updated on June 07, 2022Comments
-
Afshar Mohebi almost 2 years
I am trying to use
JWT
for authentication mechanism inASP.NET Core Web API
project. Suppose this project has notMVC
part and does not use cookie authentication. I have created my code based on this guide.Login works good and protection with
[Authorize]
attribute works ok butUser.Identity.Name
isnull
. How can I fix this?My code:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { var jwtAppSettingOptions = Configuration.GetSection(nameof(JwtIssuerOptions)); var tokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)], ValidateAudience = true, ValidAudience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)], ValidateIssuerSigningKey = true, IssuerSigningKey = _signingKey, RequireExpirationTime = true, ValidateLifetime = true, ClockSkew = TimeSpan.Zero }; app.UseJwtBearerAuthentication(new JwtBearerOptions { AutomaticAuthenticate = true, AutomaticChallenge = true, TokenValidationParameters = tokenValidationParameters, AuthenticationScheme = JwtBearerDefaults.AuthenticationScheme }); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); }
[HttpPost] [AllowAnonymous] [Route("Login")] public async Task<IActionResult> Login([FromForm] ApplicationUser applicationUser) { //assume user/pass are checked and are ok _logger.LogInformation(1, "API User logged in."); var user = await _userManager.FindByNameAsync(applicationUser.UserName); var roles = await _userManager.GetRolesAsync(user); var claims = new List<Claim> { new Claim(JwtRegisteredClaimNames.Sub, applicationUser.UserName), new Claim(ClaimTypes.NameIdentifier, applicationUser.UserName), new Claim(JwtRegisteredClaimNames.Jti, await _jwtOptions.JtiGenerator()), new Claim(JwtRegisteredClaimNames.Iat, ToUnixEpochDate(_jwtOptions.IssuedAt).ToString(), ClaimValueTypes.Integer64), new Claim("Claim", "Value") }; if (roles != null) foreach (var role in roles) claims.Add(new Claim("role", role)); // Create the JWT security token and encode it. var jwt = new JwtSecurityToken( issuer: _jwtOptions.Issuer, audience: _jwtOptions.Audience, claims: claims, notBefore: _jwtOptions.NotBefore, expires: _jwtOptions.Expiration, signingCredentials: _jwtOptions.SigningCredentials); var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt); // Serialize and return the response var response = new { access_token = encodedJwt, expires_in = (int)_jwtOptions.ValidFor.TotalSeconds }; var json = JsonConvert.SerializeObject(response, _serializerSettings); return new OkObjectResult(json); }
-
youen over 6 yearsUsing the "sub" field of the token looks more standard than the accepted answer, and also reduces the token size a little :-)
-
Telmo Marques almost 2 yearsTo use the constant:
NameClaimType = ClaimTypes.NameIdentifier
.ClaimTypes
comes fromSystem.Security.Claims