Проблема чтения Claims из JwtToken
Проблема заключается в следующем
В проекте при логине создается токен
[HttpPost("login")]
[AllowAnonymous]
public async Task<IActionResult> Login([FromBody] LoginModel model)
{
var result = await customUserManager.ValidateUserAuthorizationAsync(model.Username, model.Password);
if(result.IsSuccess)
{
var accessToken = GenerateJwtToken(result.User);
var refreshToken = GenerateRefreshToken();
SaveRefreshToken(result.User.Id, refreshToken);
return Ok(new { accessToken, refreshToken, result.User.UserName, result.User.Email });
}
return Unauthorized(new { message = result.Message });
}
Генерация токена происходит следующим образом
private string GenerateJwtToken(AspNetUser user)
{
var jwtSettings = this.configuration.GetSection("Jwt").Get<JwtSettings>();
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings!.Key));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[] { new Claim(JwtRegisteredClaimNames.Name, user.UserName),
new Claim(JwtRegisteredClaimNames.NameId, user.Id),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())}),
Expires = DateTime.UtcNow.AddHours(1),
Issuer = jwtSettings.Issuer,
Audience = jwtSettings.Audience,
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings!.Key)), SecurityAlgorithms.HmacSha256Signature)
};
var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
Далее я получаю токен уже с фронта и пытаюсь извлечь
var token = HttpContext.Request.Headers["Authorization"].ToString().Replace("Bearer ", string.Empty);
var jwtHandler = new JwtSecurityTokenHandler();
var jwtToken = jwtHandler.ReadToken(token) as JwtSecurityToken;
var userId = jwtToken.Claims.FirstOrDefault(c => c.Type == JwtRegisteredClaimNames.NameId)?.Value;
UserId оказывается пустым, при этом другие claim, могут быть извлечены. При изменении количества claim, могут становится недоступны различные поля. Например, обнулится Expires или другое поле. С чем может быть связана данная проблема?
Я выводил целиком subject, claims и payload, в них не все поля могут присутствовать. Было предположение, что есть ограничение на размер payload токена, но сторонние сервисы спокойно извлекают все данные из токена.
Ответы (2 шт):
Нашёл в чём ошибка. Причина была в подключенных пакетах. Программа работает, если в проекте подключена Microsoft.AspNetCore.Authentication.JwtBearer, однако перестает работать, если подключить Microsoft.IdentityModel.Tokens. Вероятно, дело в зависимостях, но при добавлении в проект последнего пакета, нужно дополнительно ставить System.IdentityModel.Tokens.Jwt, иначе токен даже валидацию не пройдет. Вернее причина даже не в этом, а в том что у меня версия пакета JwtBearer - 8.0.12, и он по умолчанию дергает IdentityModel.Tokens - 8.0.1 и IdentityModel.Tokens.Jwt - 8.0.1.
Когда я поставил IdentityModel.Tokens - 8.3.0, ему понадобился IdentityModel.Tokens.Jwt - 8.3.0, но среда мне не сказала про это
UPD: Решение, следить за обновлением пакетов, либо же задать версию в файле проекта. Может кто подскажет, какие хорошие анализаторы может есть?
Судя по вашему ответу, осмелюсь предположить, что скорее всего вы просто перепутали пакеты и использовали не тот, что вам нужен был изначально. Версии пакетов имею влияние, но они точно не могут вести себя описанным образом
Если вы используете userManager
и signInManager
вам не нужно вручную генерировать и передавать токены, поскольку если вы выбрали автоматизированный путь, то данные менеджеры уже имеют генерировать необходимые вам токены
Аналогично, валидировать их так же не имеет смысла, поскольку менеджер выше указанные менеджеры так же имеют их сами читать и делать все необходимые процедуры