При переносе существующего проекта API в .NET 8 возникает ошибка при создании токенов JWT.C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 При переносе существующего проекта API в .NET 8 возникает ошибка при создании токенов JWT.

Сообщение Anonymous »

Я только что обновил веб-API ASP.NET Core 6 до .NET 8 (обратите внимание, что в .NET 6 все работало отлично), и при создании токена JWT я получаю следующую ошибку:

System.ArgumentOutOfRangeException: 'IDX10720: невозможно создать KeyedHashAlgorithm для алгоритма 'HS256', размер ключа должен быть больше чем: «256» бит, ключ имеет «152» бита. (Параметр 'keyBytes')'

Исходя из того, что я понял из этой ошибки, похоже, что появилось новое требование относительно того, как долго должен храниться секрет. быть так, я сделал секрет длиннее, что работает для создания токена, но при чтении токена я получаю совершенно новую ошибку

System.ArgumentException: 'IDX12723: Невозможно декодировать полезная нагрузка '[PII типа System.String' скрыта. Для получения более подробной информации см. https://aka.ms/IdentityModel/PII.]' как строку в кодировке Base64Url.'

Изменить: вот внутренний исключение, возможно, это может пролить некоторый свет

JsonException: IDX11020: значение JSON типа: 'String' не удалось преобразовать в 'JsonTokenType.Номер'. Чтение: «System.IdentityModel.Tokens.Jwt.JwtPayload.iat», позиция: «52», CurrentDepth: «1», BytesConsumed: «75».

Есть ли здесь какие-то критические изменения для обработки токенов JWT?
Вот код частного метода, читающего токен
private User? _GetIdentity(HttpContext context, string token)
{
try
{
var handler = new JwtSecurityTokenHandler();
//var jsonToken = handler.ReadToken(token);
var tokenS = handler.ReadToken(token) as JwtSecurityToken;//error happens here

var user = new User
{
Id = tokenS.Claims.First(claim => claim.Type == ClaimTypes.NameIdentifier).Value,
UserName = tokenS.Claims.First(claim => claim.Type == ClaimTypes.Name).Value,
Email = tokenS.Claims.First(claim => claim.Type == ClaimTypes.Email).Value,
Role = tokenS.Claims.First(claim => claim.Type == ClaimTypes.Role).Value
};

if (tokenS.ValidTo < DateTime.UtcNow)
{
throw new Exceptions.UnauthorizedAccessException($"...");
}

return user;
}
catch(Exceptions.UnauthorizedAccessException e)
{
_logger.LogError(e.Message);
throw;
}
}

Вот код класса, генерирующего токен JWT:
public class JwtService
{
private const int EXPIRATION_TOKEN_MINUTES = 25;
private const int EXPIRATION_REFRESH_DAYS = 7;
private readonly IConfiguration _configuration;

public JwtService(IConfiguration configuration)
{
_configuration = configuration;
}

public AuthenticationResponse CreateToken(IdentityUser user, IEnumerable roles)
{
var expiration = DateTime.Now.AddMinutes(EXPIRATION_TOKEN_MINUTES);
var refreshExpiration = DateTime.Now.AddDays(EXPIRATION_REFRESH_DAYS);
var token = CreateJwtToken(
CreateClaims(user, roles),
CreateSigningCredentials(),
expiration
);
var refreshToken = CreateJwtToken(
CreateRefreshTokenClaims(user.Id),
CreateSigningCredentials(),
refreshExpiration
);

var tokenHandler = new JwtSecurityTokenHandler();

return new AuthenticationResponse
{
Token = tokenHandler.WriteToken(token),
RefreshToken = tokenHandler.WriteToken(refreshToken),
Expiration = expiration
};
}

private JwtSecurityToken CreateJwtToken(Claim[] claims, SigningCredentials credentials, DateTime expiration) =>
new JwtSecurityToken(
_configuration["Jwt:Issuer"],
_configuration["Jwt:Audience"],
claims,
expires: expiration,
signingCredentials: credentials
);

private Claim[] CreateRefreshTokenClaims(string userId) =>
new[]
{
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Iat, DateTime.Now.ToString()),
new Claim(ClaimTypes.NameIdentifier, userId)
};

private Claim[] CreateClaims(IdentityUser user, IEnumerable roles) =>
new[] {
//new Claim(JwtRegisteredClaimNames.Sub, _configuration["Jwt:Subject"]),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToString()),
new Claim(ClaimTypes.NameIdentifier, user.Id),
new Claim(ClaimTypes.Name, user.UserName),
new Claim(ClaimTypes.Email, user.Email),

}
.Concat(roles.Select(r => new Claim(ClaimTypes.Role, r)).ToArray())
.ToArray();

private SigningCredentials CreateSigningCredentials() =>
new SigningCredentials(
new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(_configuration["Jwt:Secret"])
),
SecurityAlgorithms.HmacSha256
);

public ClaimsIdentity CreateClaimsIdentity(string username, string userId, IEnumerable roles)
{
List claims = new List
{
new Claim(ClaimTypes.Name, username),
new Claim(ClaimTypes.NameIdentifier, userId)
};

claims.AddRange(roles.Select(role => new Claim(ClaimTypes.Role, role)));

ClaimsIdentity identity = new ClaimsIdentity(
claims,
"Token",
ClaimTypes.Name,
ClaimTypes.Role
);

return identity;
}

public ClaimsPrincipal ValidateToken(string token)
{
try
{
var tokenHandler = new JwtSecurityTokenHandler();

// Set the token validation parameters
var validationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidAudience = _configuration["Jwt:Audience"],
ValidIssuer = _configuration["Jwt:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(_configuration["Jwt:Secret"])
)
};

// Validate and parse the token
var principal = tokenHandler.ValidateToken(token, validationParameters, out var _);

return principal;
}
catch
{
// Token validation failed
return null;
}
}
}


Подробнее здесь: https://stackoverflow.com/questions/775 ... jwt-tokens
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»