JWT токены в C# (.NET): полное руководство по работе с System.IdentityModel.Tokens.Jwt
JSON Web Token (JWT) — это компактный, URL-безопасный формат для передачи данных между сторонами в виде JSON-объекта. В экосистеме C# (.NET) для работы с JWT используется мощная библиотека System.IdentityModel.Tokens.Jwt, которая входит в состав пакета Microsoft.IdentityModel.Tokens. Этот инструмент позволяет генерировать, подписывать, проверять и декодировать JWT-токены, обеспечивая безопасную аутентификацию и обмен данными в веб-приложениях, API и микросервисах.
Установка библиотеки
Для начала работы добавьте NuGet-пакет в проект. Выполните команду в консоли диспетчера пакетов:
dotnet add package System.IdentityModel.Tokens.Jwt
Или через Package Manager Console в Visual Studio:
Install-Package System.IdentityModel.Tokens.Jwt
Основные компоненты библиотеки
JwtSecurityTokenHandler— главный класс для создания, сериализации и проверки токенов.SecurityTokenDescriptor— описание токена: claims, время жизни, подпись.SymmetricSecurityKey— симметричный ключ для подписи (HS256, HS384, HS512).SigningCredentials— учётные данные подписи (алгоритм + ключ).TokenValidationParameters— параметры валидации (проверка подписи, времени жизни, издателя).
Генерация JWT токена в C#
Создадим простой токен с пользовательскими claims (утверждениями) и временем жизни 1 час:
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;
public string GenerateToken()
{
var secretKey = "my_super_secret_key_1234567890!";
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim(ClaimTypes.Name, "Иван Петров"),
new Claim(ClaimTypes.Email, "ivan@example.com"),
new Claim(ClaimTypes.Role, "Admin")
};
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
Expires = DateTime.UtcNow.AddHours(1),
Issuer = "MyApp",
Audience = "MyAppUsers",
SigningCredentials = credentials
};
var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
Проверка (верификация) JWT токена
При получении токена от клиента необходимо проверить его подпись, срок действия и другие параметры:
public ClaimsPrincipal ValidateToken(string token)
{
var secretKey = "my_super_secret_key_1234567890!";
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));
var tokenHandler = new JwtSecurityTokenHandler();
var validationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = "MyApp",
ValidateAudience = true,
ValidAudience = "MyAppUsers",
ValidateLifetime = true,
IssuerSigningKey = key,
ClockSkew = TimeSpan.Zero // убираем запас времени по умолчанию
};
try
{
var principal = tokenHandler.ValidateToken(token, validationParameters, out SecurityToken validatedToken);
return principal;
}
catch (SecurityTokenExpiredException)
{
Console.WriteLine("Токен истёк");
return null;
}
catch (SecurityTokenInvalidSignatureException)
{
Console.WriteLine("Неверная подпись токена");
return null;
}
}
Декодирование токена без проверки подписи
Иногда нужно просто прочитать данные из токена (например, для отладки). Используйте метод ReadJwtToken:
public void DecodeToken(string token)
{
var tokenHandler = new JwtSecurityTokenHandler();
var jwtToken = tokenHandler.ReadJwtToken(token);
Console.WriteLine($"Издатель: {jwtToken.Issuer}");
Console.WriteLine($"Срок действия до: {jwtToken.ValidTo}");
foreach (var claim in jwtToken.Claims)
{
Console.WriteLine($"{claim.Type}: {claim.Value}");
}
}
Асинхронная проверка токена
Библиотека поддерживает асинхронные методы для работы в высоконагруженных приложениях:
public async Task<ClaimsPrincipal> ValidateTokenAsync(string token)
{
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("my_super_secret_key_1234567890!"));
var tokenHandler = new JwtSecurityTokenHandler();
var validationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = "MyApp",
ValidateAudience =