UseJwtBearerAuthentication does not get the value of User.Identity.Name

I am trying to use JWT for the authentication mechanism in an ASP.NET Core Web API project. Suppose this project does not have an MVC part and does not use cookie authentication. I created my code based on this guide .

The input works fine, and the protection with the [Authorize] attribute works fine, but User.Identity.Name is null . How can i fix this?

My code is:

 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); } 
+6
source share
2 answers

in your statements (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 must contain the username.

+8
source

Another option is to set the namespace for JwtRegisteredClaimNames.Sub tokenValidationParameters . This will allow you to 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 commented on my blog about this topic:

"Hello,

Thank you for your help. It worked for me. For greater consistency and security, you can use the ClaimTypes.NameIdentifier property (in the System.Security.Claims namespace) instead of a string string. "

I have not tested this, but it looks a little more elegant than using a namespace string.

+2
source

Source: https://habr.com/ru/post/1014371/


All Articles