ASP.Net Core JWT Login not setting HttpContext.User.Claims









up vote
0
down vote

favorite
1












I have the following for my login code, and another method to retrieve the user ID in another call.



 // POST: /api/Account/Login
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> Login([FromBody]LoginViewModel model)

if (ModelState.IsValid)

var user = await _userManager.FindByEmailAsync(model.Email);
if (user != null)

if (!await _userManager.IsEmailConfirmedAsync(user))

ModelState.AddModelError(string.Empty,
"You must have a confirmed email to log in.");
return BadRequest(Errors.AddErrorToModelState("Email", "You must have a confirmed email to log in.", ModelState));



var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);

if (result.Succeeded)

// IS THIS NEEDED? --> // HttpContext.User = await _userClaimsPrincipalFactory.CreateAsync(user);
var tokens = _antiforgery.GetAndStoreTokens(HttpContext);

var identity = _jwtFactory.GenerateClaimsIdentity(model.Email, user.Id);
_logger.LogInformation(1, "User logged in.");
var jwt = await Tokens.GenerateJwt(identity, _jwtFactory, model.Email, _jwtOptions, new JsonSerializerSettings Formatting = Formatting.Indented );
return new OkObjectResult(jwt);


if (result.RequiresTwoFactor)

//return RedirectToAction(nameof(SendCode), new ReturnUrl = returnUrl, RememberMe = model.RememberMe );


if (result.IsLockedOut)

string message = "User account locked out.";
_logger.LogWarning(2, message);
return BadRequest(Errors.AddErrorToModelState("Email", message, ModelState));


if (result.IsNotAllowed)

string message = "User account is not allowed to sign in.";
_logger.LogWarning(2, message);
return BadRequest(Errors.AddErrorToModelState("Email", message, ModelState));


return BadRequest(Errors.AddErrorToModelState("", "Sign in failed.", ModelState));


return BadRequest(Errors.AddErrorToModelState("", "", ModelState));


public string GetUserId()

string username = string.Empty;

ClaimsPrincipal principal = HttpContext.User as ClaimsPrincipal;

if (HttpContext.User != null)

var id = HttpContext.User.FindFirst(ClaimTypes.NameIdentifier);

if (id != null)

username = id.Value;



return username;



This is the code for GenerateJwt. (Are these fields standard? I see other fields being set in other code, such as in https://code-maze.com/authentication-aspnetcore-jwt-1/.)



 public static async Task<string> GenerateJwt(ClaimsIdentity identity, IJwtFactory jwtFactory,string userName, JwtIssuerOptions jwtOptions, JsonSerializerSettings serializerSettings)

var response = new

id = identity.Claims.Single(c => c.Type == "id").Value,
auth_token = await jwtFactory.GenerateEncodedToken(userName, identity),
expires_in = (int)jwtOptions.ValidFor.TotalSeconds
; // see GenerateEncodedToken pasted below.

return JsonConvert.SerializeObject(response, serializerSettings);


public async Task<string> GenerateEncodedToken(string userName, ClaimsIdentity identity)

var claims = new

new Claim(JwtRegisteredClaimNames.Sub, userName),
new Claim(JwtRegisteredClaimNames.Jti, await _jwtOptions.JtiGenerator()),
new Claim(JwtRegisteredClaimNames.Iat, ToUnixEpochDate(_jwtOptions.IssuedAt).ToString(), ClaimValueTypes.Integer64),
identity.FindFirst(Helpers.Constants.Strings.JwtClaimIdentifiers.Rol),
identity.FindFirst(Helpers.Constants.Strings.JwtClaimIdentifiers.Id)
;

// 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);

return encodedJwt;



These are the relevant lines in ConfigureServices.



 // jwt wire up
// Get options from app settings
var jwtAppSettingOptions = Configuration.GetSection(nameof(JwtIssuerOptions));

// Configure JwtIssuerOptions
services.Configure<JwtIssuerOptions>(options =>

options.Issuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
options.Audience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)];
options.SigningCredentials = new SigningCredentials(_signingKey, SecurityAlgorithms.HmacSha256);
);

var tokenValidationParameters = new TokenValidationParameters

ValidateIssuer = true,
ValidIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)],

ValidateAudience = true,
ValidAudience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)],

ValidateIssuerSigningKey = true,
IssuerSigningKey = _signingKey,

RequireExpirationTime = false,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
;

services.AddAuthentication(options =>

options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

).AddJwtBearer(configureOptions =>

configureOptions.ClaimsIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
configureOptions.TokenValidationParameters = tokenValidationParameters;
configureOptions.SaveToken = true;
configureOptions.RequireHttpsMetadata = false;
);

// api user claim policy
services.AddAuthorization(options =>

options.AddPolicy("ApiUser", policy => policy.RequireClaim(Constants.Strings.JwtClaimIdentifiers.Rol, Constants.Strings.JwtClaims.ApiAccess));
);

// add identity
var builder = services.AddIdentity<AppUser, AppRole>(o =>

// configure identity options
o.Password.RequireDigit = false;
o.Password.RequireLowercase = false;
o.Password.RequireUppercase = false;
o.Password.RequireNonAlphanumeric = false;
o.Password.RequiredLength = 6;
)
.AddSignInManager<SignInManager<AppUser>>()
.AddEntityFrameworkStores<AppIdentityDbContext>()
.AddDefaultTokenProviders();


I'm using the following to pass my token from Angular.



 private authHeader(): HttpHeaders 
let headers = new HttpHeaders();
if (isPlatformBrowser(this.platformId))
headers = headers.set('Content-Type', 'application/json');
let authToken = this.windowRefService.nativeWindow.localStorage.getItem('auth_token');
headers = headers.set('Authorization', authToken);
headers = headers.set('X-XSRF-TOKEN', this.getCookie('XSRF-TOKEN'));


return headers;


protected jsonAuthRequestOptions = headers: this.authHeader() ;

public loggedInAs(): Observable<string>
return this.http.post<any>(this.baseUrl + "api/Account/GetUserId", , this.jsonAuthRequestOptions)
.map(data =>
if (data)
return data;


return '';
)
.catch(this.handleError);



Does JWT authentication automatically set HttpContext.User? Or do I have to do that explicitly?



My succeeding call fails. (User has no claims, though HttpContext.User is not null.) I don't know whether the problem is with relying on HttpContext.User, or whether there is something wrong with the token generation / consumption.










share|improve this question























  • Are you calling services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(... and app.UseAuthentication(); in Startup.cs?
    – Albert
    2 days ago











  • Yes. services.AddAuthentication(options => options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; ).AddJwtBearer(configureOptions => configureOptions.ClaimsIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)]; configureOptions.TokenValidationParameters = tokenValidationParameters; configureOptions.SaveToken = true; );
    – Jonas Arcangel
    2 days ago










  • And did you set the app.UseAuthentication() on Configure method within Startup.cs file as well, before the UseMvc? Double-check here
    – Anderson Matos
    2 days ago










  • I also have app.UseAuthentication() as well as app.UseJwtTokenMiddleware() before UseMvc().
    – Jonas Arcangel
    2 days ago










  • HttpContext.User exists, so I think it is getting authenticated. It's just that the Claims is empty.
    – Jonas Arcangel
    2 days ago














up vote
0
down vote

favorite
1












I have the following for my login code, and another method to retrieve the user ID in another call.



 // POST: /api/Account/Login
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> Login([FromBody]LoginViewModel model)

if (ModelState.IsValid)

var user = await _userManager.FindByEmailAsync(model.Email);
if (user != null)

if (!await _userManager.IsEmailConfirmedAsync(user))

ModelState.AddModelError(string.Empty,
"You must have a confirmed email to log in.");
return BadRequest(Errors.AddErrorToModelState("Email", "You must have a confirmed email to log in.", ModelState));



var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);

if (result.Succeeded)

// IS THIS NEEDED? --> // HttpContext.User = await _userClaimsPrincipalFactory.CreateAsync(user);
var tokens = _antiforgery.GetAndStoreTokens(HttpContext);

var identity = _jwtFactory.GenerateClaimsIdentity(model.Email, user.Id);
_logger.LogInformation(1, "User logged in.");
var jwt = await Tokens.GenerateJwt(identity, _jwtFactory, model.Email, _jwtOptions, new JsonSerializerSettings Formatting = Formatting.Indented );
return new OkObjectResult(jwt);


if (result.RequiresTwoFactor)

//return RedirectToAction(nameof(SendCode), new ReturnUrl = returnUrl, RememberMe = model.RememberMe );


if (result.IsLockedOut)

string message = "User account locked out.";
_logger.LogWarning(2, message);
return BadRequest(Errors.AddErrorToModelState("Email", message, ModelState));


if (result.IsNotAllowed)

string message = "User account is not allowed to sign in.";
_logger.LogWarning(2, message);
return BadRequest(Errors.AddErrorToModelState("Email", message, ModelState));


return BadRequest(Errors.AddErrorToModelState("", "Sign in failed.", ModelState));


return BadRequest(Errors.AddErrorToModelState("", "", ModelState));


public string GetUserId()

string username = string.Empty;

ClaimsPrincipal principal = HttpContext.User as ClaimsPrincipal;

if (HttpContext.User != null)

var id = HttpContext.User.FindFirst(ClaimTypes.NameIdentifier);

if (id != null)

username = id.Value;



return username;



This is the code for GenerateJwt. (Are these fields standard? I see other fields being set in other code, such as in https://code-maze.com/authentication-aspnetcore-jwt-1/.)



 public static async Task<string> GenerateJwt(ClaimsIdentity identity, IJwtFactory jwtFactory,string userName, JwtIssuerOptions jwtOptions, JsonSerializerSettings serializerSettings)

var response = new

id = identity.Claims.Single(c => c.Type == "id").Value,
auth_token = await jwtFactory.GenerateEncodedToken(userName, identity),
expires_in = (int)jwtOptions.ValidFor.TotalSeconds
; // see GenerateEncodedToken pasted below.

return JsonConvert.SerializeObject(response, serializerSettings);


public async Task<string> GenerateEncodedToken(string userName, ClaimsIdentity identity)

var claims = new

new Claim(JwtRegisteredClaimNames.Sub, userName),
new Claim(JwtRegisteredClaimNames.Jti, await _jwtOptions.JtiGenerator()),
new Claim(JwtRegisteredClaimNames.Iat, ToUnixEpochDate(_jwtOptions.IssuedAt).ToString(), ClaimValueTypes.Integer64),
identity.FindFirst(Helpers.Constants.Strings.JwtClaimIdentifiers.Rol),
identity.FindFirst(Helpers.Constants.Strings.JwtClaimIdentifiers.Id)
;

// 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);

return encodedJwt;



These are the relevant lines in ConfigureServices.



 // jwt wire up
// Get options from app settings
var jwtAppSettingOptions = Configuration.GetSection(nameof(JwtIssuerOptions));

// Configure JwtIssuerOptions
services.Configure<JwtIssuerOptions>(options =>

options.Issuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
options.Audience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)];
options.SigningCredentials = new SigningCredentials(_signingKey, SecurityAlgorithms.HmacSha256);
);

var tokenValidationParameters = new TokenValidationParameters

ValidateIssuer = true,
ValidIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)],

ValidateAudience = true,
ValidAudience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)],

ValidateIssuerSigningKey = true,
IssuerSigningKey = _signingKey,

RequireExpirationTime = false,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
;

services.AddAuthentication(options =>

options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

).AddJwtBearer(configureOptions =>

configureOptions.ClaimsIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
configureOptions.TokenValidationParameters = tokenValidationParameters;
configureOptions.SaveToken = true;
configureOptions.RequireHttpsMetadata = false;
);

// api user claim policy
services.AddAuthorization(options =>

options.AddPolicy("ApiUser", policy => policy.RequireClaim(Constants.Strings.JwtClaimIdentifiers.Rol, Constants.Strings.JwtClaims.ApiAccess));
);

// add identity
var builder = services.AddIdentity<AppUser, AppRole>(o =>

// configure identity options
o.Password.RequireDigit = false;
o.Password.RequireLowercase = false;
o.Password.RequireUppercase = false;
o.Password.RequireNonAlphanumeric = false;
o.Password.RequiredLength = 6;
)
.AddSignInManager<SignInManager<AppUser>>()
.AddEntityFrameworkStores<AppIdentityDbContext>()
.AddDefaultTokenProviders();


I'm using the following to pass my token from Angular.



 private authHeader(): HttpHeaders 
let headers = new HttpHeaders();
if (isPlatformBrowser(this.platformId))
headers = headers.set('Content-Type', 'application/json');
let authToken = this.windowRefService.nativeWindow.localStorage.getItem('auth_token');
headers = headers.set('Authorization', authToken);
headers = headers.set('X-XSRF-TOKEN', this.getCookie('XSRF-TOKEN'));


return headers;


protected jsonAuthRequestOptions = headers: this.authHeader() ;

public loggedInAs(): Observable<string>
return this.http.post<any>(this.baseUrl + "api/Account/GetUserId", , this.jsonAuthRequestOptions)
.map(data =>
if (data)
return data;


return '';
)
.catch(this.handleError);



Does JWT authentication automatically set HttpContext.User? Or do I have to do that explicitly?



My succeeding call fails. (User has no claims, though HttpContext.User is not null.) I don't know whether the problem is with relying on HttpContext.User, or whether there is something wrong with the token generation / consumption.










share|improve this question























  • Are you calling services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(... and app.UseAuthentication(); in Startup.cs?
    – Albert
    2 days ago











  • Yes. services.AddAuthentication(options => options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; ).AddJwtBearer(configureOptions => configureOptions.ClaimsIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)]; configureOptions.TokenValidationParameters = tokenValidationParameters; configureOptions.SaveToken = true; );
    – Jonas Arcangel
    2 days ago










  • And did you set the app.UseAuthentication() on Configure method within Startup.cs file as well, before the UseMvc? Double-check here
    – Anderson Matos
    2 days ago










  • I also have app.UseAuthentication() as well as app.UseJwtTokenMiddleware() before UseMvc().
    – Jonas Arcangel
    2 days ago










  • HttpContext.User exists, so I think it is getting authenticated. It's just that the Claims is empty.
    – Jonas Arcangel
    2 days ago












up vote
0
down vote

favorite
1









up vote
0
down vote

favorite
1






1





I have the following for my login code, and another method to retrieve the user ID in another call.



 // POST: /api/Account/Login
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> Login([FromBody]LoginViewModel model)

if (ModelState.IsValid)

var user = await _userManager.FindByEmailAsync(model.Email);
if (user != null)

if (!await _userManager.IsEmailConfirmedAsync(user))

ModelState.AddModelError(string.Empty,
"You must have a confirmed email to log in.");
return BadRequest(Errors.AddErrorToModelState("Email", "You must have a confirmed email to log in.", ModelState));



var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);

if (result.Succeeded)

// IS THIS NEEDED? --> // HttpContext.User = await _userClaimsPrincipalFactory.CreateAsync(user);
var tokens = _antiforgery.GetAndStoreTokens(HttpContext);

var identity = _jwtFactory.GenerateClaimsIdentity(model.Email, user.Id);
_logger.LogInformation(1, "User logged in.");
var jwt = await Tokens.GenerateJwt(identity, _jwtFactory, model.Email, _jwtOptions, new JsonSerializerSettings Formatting = Formatting.Indented );
return new OkObjectResult(jwt);


if (result.RequiresTwoFactor)

//return RedirectToAction(nameof(SendCode), new ReturnUrl = returnUrl, RememberMe = model.RememberMe );


if (result.IsLockedOut)

string message = "User account locked out.";
_logger.LogWarning(2, message);
return BadRequest(Errors.AddErrorToModelState("Email", message, ModelState));


if (result.IsNotAllowed)

string message = "User account is not allowed to sign in.";
_logger.LogWarning(2, message);
return BadRequest(Errors.AddErrorToModelState("Email", message, ModelState));


return BadRequest(Errors.AddErrorToModelState("", "Sign in failed.", ModelState));


return BadRequest(Errors.AddErrorToModelState("", "", ModelState));


public string GetUserId()

string username = string.Empty;

ClaimsPrincipal principal = HttpContext.User as ClaimsPrincipal;

if (HttpContext.User != null)

var id = HttpContext.User.FindFirst(ClaimTypes.NameIdentifier);

if (id != null)

username = id.Value;



return username;



This is the code for GenerateJwt. (Are these fields standard? I see other fields being set in other code, such as in https://code-maze.com/authentication-aspnetcore-jwt-1/.)



 public static async Task<string> GenerateJwt(ClaimsIdentity identity, IJwtFactory jwtFactory,string userName, JwtIssuerOptions jwtOptions, JsonSerializerSettings serializerSettings)

var response = new

id = identity.Claims.Single(c => c.Type == "id").Value,
auth_token = await jwtFactory.GenerateEncodedToken(userName, identity),
expires_in = (int)jwtOptions.ValidFor.TotalSeconds
; // see GenerateEncodedToken pasted below.

return JsonConvert.SerializeObject(response, serializerSettings);


public async Task<string> GenerateEncodedToken(string userName, ClaimsIdentity identity)

var claims = new

new Claim(JwtRegisteredClaimNames.Sub, userName),
new Claim(JwtRegisteredClaimNames.Jti, await _jwtOptions.JtiGenerator()),
new Claim(JwtRegisteredClaimNames.Iat, ToUnixEpochDate(_jwtOptions.IssuedAt).ToString(), ClaimValueTypes.Integer64),
identity.FindFirst(Helpers.Constants.Strings.JwtClaimIdentifiers.Rol),
identity.FindFirst(Helpers.Constants.Strings.JwtClaimIdentifiers.Id)
;

// 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);

return encodedJwt;



These are the relevant lines in ConfigureServices.



 // jwt wire up
// Get options from app settings
var jwtAppSettingOptions = Configuration.GetSection(nameof(JwtIssuerOptions));

// Configure JwtIssuerOptions
services.Configure<JwtIssuerOptions>(options =>

options.Issuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
options.Audience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)];
options.SigningCredentials = new SigningCredentials(_signingKey, SecurityAlgorithms.HmacSha256);
);

var tokenValidationParameters = new TokenValidationParameters

ValidateIssuer = true,
ValidIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)],

ValidateAudience = true,
ValidAudience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)],

ValidateIssuerSigningKey = true,
IssuerSigningKey = _signingKey,

RequireExpirationTime = false,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
;

services.AddAuthentication(options =>

options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

).AddJwtBearer(configureOptions =>

configureOptions.ClaimsIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
configureOptions.TokenValidationParameters = tokenValidationParameters;
configureOptions.SaveToken = true;
configureOptions.RequireHttpsMetadata = false;
);

// api user claim policy
services.AddAuthorization(options =>

options.AddPolicy("ApiUser", policy => policy.RequireClaim(Constants.Strings.JwtClaimIdentifiers.Rol, Constants.Strings.JwtClaims.ApiAccess));
);

// add identity
var builder = services.AddIdentity<AppUser, AppRole>(o =>

// configure identity options
o.Password.RequireDigit = false;
o.Password.RequireLowercase = false;
o.Password.RequireUppercase = false;
o.Password.RequireNonAlphanumeric = false;
o.Password.RequiredLength = 6;
)
.AddSignInManager<SignInManager<AppUser>>()
.AddEntityFrameworkStores<AppIdentityDbContext>()
.AddDefaultTokenProviders();


I'm using the following to pass my token from Angular.



 private authHeader(): HttpHeaders 
let headers = new HttpHeaders();
if (isPlatformBrowser(this.platformId))
headers = headers.set('Content-Type', 'application/json');
let authToken = this.windowRefService.nativeWindow.localStorage.getItem('auth_token');
headers = headers.set('Authorization', authToken);
headers = headers.set('X-XSRF-TOKEN', this.getCookie('XSRF-TOKEN'));


return headers;


protected jsonAuthRequestOptions = headers: this.authHeader() ;

public loggedInAs(): Observable<string>
return this.http.post<any>(this.baseUrl + "api/Account/GetUserId", , this.jsonAuthRequestOptions)
.map(data =>
if (data)
return data;


return '';
)
.catch(this.handleError);



Does JWT authentication automatically set HttpContext.User? Or do I have to do that explicitly?



My succeeding call fails. (User has no claims, though HttpContext.User is not null.) I don't know whether the problem is with relying on HttpContext.User, or whether there is something wrong with the token generation / consumption.










share|improve this question















I have the following for my login code, and another method to retrieve the user ID in another call.



 // POST: /api/Account/Login
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> Login([FromBody]LoginViewModel model)

if (ModelState.IsValid)

var user = await _userManager.FindByEmailAsync(model.Email);
if (user != null)

if (!await _userManager.IsEmailConfirmedAsync(user))

ModelState.AddModelError(string.Empty,
"You must have a confirmed email to log in.");
return BadRequest(Errors.AddErrorToModelState("Email", "You must have a confirmed email to log in.", ModelState));



var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);

if (result.Succeeded)

// IS THIS NEEDED? --> // HttpContext.User = await _userClaimsPrincipalFactory.CreateAsync(user);
var tokens = _antiforgery.GetAndStoreTokens(HttpContext);

var identity = _jwtFactory.GenerateClaimsIdentity(model.Email, user.Id);
_logger.LogInformation(1, "User logged in.");
var jwt = await Tokens.GenerateJwt(identity, _jwtFactory, model.Email, _jwtOptions, new JsonSerializerSettings Formatting = Formatting.Indented );
return new OkObjectResult(jwt);


if (result.RequiresTwoFactor)

//return RedirectToAction(nameof(SendCode), new ReturnUrl = returnUrl, RememberMe = model.RememberMe );


if (result.IsLockedOut)

string message = "User account locked out.";
_logger.LogWarning(2, message);
return BadRequest(Errors.AddErrorToModelState("Email", message, ModelState));


if (result.IsNotAllowed)

string message = "User account is not allowed to sign in.";
_logger.LogWarning(2, message);
return BadRequest(Errors.AddErrorToModelState("Email", message, ModelState));


return BadRequest(Errors.AddErrorToModelState("", "Sign in failed.", ModelState));


return BadRequest(Errors.AddErrorToModelState("", "", ModelState));


public string GetUserId()

string username = string.Empty;

ClaimsPrincipal principal = HttpContext.User as ClaimsPrincipal;

if (HttpContext.User != null)

var id = HttpContext.User.FindFirst(ClaimTypes.NameIdentifier);

if (id != null)

username = id.Value;



return username;



This is the code for GenerateJwt. (Are these fields standard? I see other fields being set in other code, such as in https://code-maze.com/authentication-aspnetcore-jwt-1/.)



 public static async Task<string> GenerateJwt(ClaimsIdentity identity, IJwtFactory jwtFactory,string userName, JwtIssuerOptions jwtOptions, JsonSerializerSettings serializerSettings)

var response = new

id = identity.Claims.Single(c => c.Type == "id").Value,
auth_token = await jwtFactory.GenerateEncodedToken(userName, identity),
expires_in = (int)jwtOptions.ValidFor.TotalSeconds
; // see GenerateEncodedToken pasted below.

return JsonConvert.SerializeObject(response, serializerSettings);


public async Task<string> GenerateEncodedToken(string userName, ClaimsIdentity identity)

var claims = new

new Claim(JwtRegisteredClaimNames.Sub, userName),
new Claim(JwtRegisteredClaimNames.Jti, await _jwtOptions.JtiGenerator()),
new Claim(JwtRegisteredClaimNames.Iat, ToUnixEpochDate(_jwtOptions.IssuedAt).ToString(), ClaimValueTypes.Integer64),
identity.FindFirst(Helpers.Constants.Strings.JwtClaimIdentifiers.Rol),
identity.FindFirst(Helpers.Constants.Strings.JwtClaimIdentifiers.Id)
;

// 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);

return encodedJwt;



These are the relevant lines in ConfigureServices.



 // jwt wire up
// Get options from app settings
var jwtAppSettingOptions = Configuration.GetSection(nameof(JwtIssuerOptions));

// Configure JwtIssuerOptions
services.Configure<JwtIssuerOptions>(options =>

options.Issuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
options.Audience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)];
options.SigningCredentials = new SigningCredentials(_signingKey, SecurityAlgorithms.HmacSha256);
);

var tokenValidationParameters = new TokenValidationParameters

ValidateIssuer = true,
ValidIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)],

ValidateAudience = true,
ValidAudience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)],

ValidateIssuerSigningKey = true,
IssuerSigningKey = _signingKey,

RequireExpirationTime = false,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
;

services.AddAuthentication(options =>

options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

).AddJwtBearer(configureOptions =>

configureOptions.ClaimsIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
configureOptions.TokenValidationParameters = tokenValidationParameters;
configureOptions.SaveToken = true;
configureOptions.RequireHttpsMetadata = false;
);

// api user claim policy
services.AddAuthorization(options =>

options.AddPolicy("ApiUser", policy => policy.RequireClaim(Constants.Strings.JwtClaimIdentifiers.Rol, Constants.Strings.JwtClaims.ApiAccess));
);

// add identity
var builder = services.AddIdentity<AppUser, AppRole>(o =>

// configure identity options
o.Password.RequireDigit = false;
o.Password.RequireLowercase = false;
o.Password.RequireUppercase = false;
o.Password.RequireNonAlphanumeric = false;
o.Password.RequiredLength = 6;
)
.AddSignInManager<SignInManager<AppUser>>()
.AddEntityFrameworkStores<AppIdentityDbContext>()
.AddDefaultTokenProviders();


I'm using the following to pass my token from Angular.



 private authHeader(): HttpHeaders 
let headers = new HttpHeaders();
if (isPlatformBrowser(this.platformId))
headers = headers.set('Content-Type', 'application/json');
let authToken = this.windowRefService.nativeWindow.localStorage.getItem('auth_token');
headers = headers.set('Authorization', authToken);
headers = headers.set('X-XSRF-TOKEN', this.getCookie('XSRF-TOKEN'));


return headers;


protected jsonAuthRequestOptions = headers: this.authHeader() ;

public loggedInAs(): Observable<string>
return this.http.post<any>(this.baseUrl + "api/Account/GetUserId", , this.jsonAuthRequestOptions)
.map(data =>
if (data)
return data;


return '';
)
.catch(this.handleError);



Does JWT authentication automatically set HttpContext.User? Or do I have to do that explicitly?



My succeeding call fails. (User has no claims, though HttpContext.User is not null.) I don't know whether the problem is with relying on HttpContext.User, or whether there is something wrong with the token generation / consumption.







asp.net-core jwt






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited yesterday

























asked 2 days ago









Jonas Arcangel

1,82443162




1,82443162











  • Are you calling services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(... and app.UseAuthentication(); in Startup.cs?
    – Albert
    2 days ago











  • Yes. services.AddAuthentication(options => options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; ).AddJwtBearer(configureOptions => configureOptions.ClaimsIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)]; configureOptions.TokenValidationParameters = tokenValidationParameters; configureOptions.SaveToken = true; );
    – Jonas Arcangel
    2 days ago










  • And did you set the app.UseAuthentication() on Configure method within Startup.cs file as well, before the UseMvc? Double-check here
    – Anderson Matos
    2 days ago










  • I also have app.UseAuthentication() as well as app.UseJwtTokenMiddleware() before UseMvc().
    – Jonas Arcangel
    2 days ago










  • HttpContext.User exists, so I think it is getting authenticated. It's just that the Claims is empty.
    – Jonas Arcangel
    2 days ago
















  • Are you calling services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(... and app.UseAuthentication(); in Startup.cs?
    – Albert
    2 days ago











  • Yes. services.AddAuthentication(options => options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; ).AddJwtBearer(configureOptions => configureOptions.ClaimsIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)]; configureOptions.TokenValidationParameters = tokenValidationParameters; configureOptions.SaveToken = true; );
    – Jonas Arcangel
    2 days ago










  • And did you set the app.UseAuthentication() on Configure method within Startup.cs file as well, before the UseMvc? Double-check here
    – Anderson Matos
    2 days ago










  • I also have app.UseAuthentication() as well as app.UseJwtTokenMiddleware() before UseMvc().
    – Jonas Arcangel
    2 days ago










  • HttpContext.User exists, so I think it is getting authenticated. It's just that the Claims is empty.
    – Jonas Arcangel
    2 days ago















Are you calling services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(... and app.UseAuthentication(); in Startup.cs?
– Albert
2 days ago





Are you calling services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(... and app.UseAuthentication(); in Startup.cs?
– Albert
2 days ago













Yes. services.AddAuthentication(options => options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; ).AddJwtBearer(configureOptions => configureOptions.ClaimsIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)]; configureOptions.TokenValidationParameters = tokenValidationParameters; configureOptions.SaveToken = true; );
– Jonas Arcangel
2 days ago




Yes. services.AddAuthentication(options => options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; ).AddJwtBearer(configureOptions => configureOptions.ClaimsIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)]; configureOptions.TokenValidationParameters = tokenValidationParameters; configureOptions.SaveToken = true; );
– Jonas Arcangel
2 days ago












And did you set the app.UseAuthentication() on Configure method within Startup.cs file as well, before the UseMvc? Double-check here
– Anderson Matos
2 days ago




And did you set the app.UseAuthentication() on Configure method within Startup.cs file as well, before the UseMvc? Double-check here
– Anderson Matos
2 days ago












I also have app.UseAuthentication() as well as app.UseJwtTokenMiddleware() before UseMvc().
– Jonas Arcangel
2 days ago




I also have app.UseAuthentication() as well as app.UseJwtTokenMiddleware() before UseMvc().
– Jonas Arcangel
2 days ago












HttpContext.User exists, so I think it is getting authenticated. It's just that the Claims is empty.
– Jonas Arcangel
2 days ago




HttpContext.User exists, so I think it is getting authenticated. It's just that the Claims is empty.
– Jonas Arcangel
2 days ago

















active

oldest

votes











Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53237854%2fasp-net-core-jwt-login-not-setting-httpcontext-user-claims%23new-answer', 'question_page');

);

Post as a guest



































active

oldest

votes













active

oldest

votes









active

oldest

votes






active

oldest

votes















 

draft saved


draft discarded















































 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53237854%2fasp-net-core-jwt-login-not-setting-httpcontext-user-claims%23new-answer', 'question_page');

);

Post as a guest














































































這個網誌中的熱門文章

Barbados

How to read a connectionString WITH PROVIDER in .NET Core?

Node.js Script on GitHub Pages or Amazon S3