Аутентификация JWT в распределенном сценарии с .NET 5

#.net-core #jwt #.net-5

Вопрос:

Я пытаюсь реализовать аутентификацию JWT в веб-интерфейсе .NET 5. Все работает нормально, пока я не добавлю в приложение дополнительные веб-серверы. Как я мог бы хранить JWT, например, в базе данных SQL Server вместо того, чтобы хранить их в памяти на одном сервере?

Вот реализация, работающая на одном сервере:

Запуск

 services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
    options.SaveToken = true;
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateIssuerSigningKey = true,
        ValidIssuer = Context.JwtIssuer,
        ValidAudience = Context.JwtIssuer,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Context.JwtSecretKey))
    };
}
 

Контроллер

 [HttpGet("Login")]
public IActionResult Login(string uid, string password)
{
    var hash = _userManager.GetPasswordHash(uid);
    if (string.IsNullOrEmpty(hash))
    {
        return NotFound("Account not found");
    }

    if (!_passwordHasher.Check(hash, password))
    {
        return Unauthorized("Uid/password not correct");
    }

    var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Context.JwtSecretKey));

    var token = new JwtSecurityToken(
        issuer: Context.JwtIssuer,
        audience: Context.JwtIssuer,
        expires: DateTime.Now.AddHours(3),
        claims: new List<Claim>() { new Claim(ClaimTypes.Name, uid)},
        signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256)
        );

    return Ok(new
    {
        token = new JwtSecurityTokenHandler().WriteToken(token),
        expiration = token.ValidTo
    });
}
 

Комментарии:

1. какая именно проблема у вас с большим количеством веб-серверов и для какой цели вам нужно хранить JWT в памяти или в базе данных?

2. Если я войду в WebAPI и, таким образом, создам Токен на стороне сервера, но при следующем вызове попаду на другой веб-сервер, токен там будет недействителен. Верно?

3. токен проверяется его подписью плюс полезной нагрузкой (время истечения срока действия, роль, аудитория), нет необходимости хранить его на стороне сервера. Обычно у вас есть один сервер авторизации (выдающий токен) и несколько серверов ресурсов. Серверы ресурсов имеют доступ к одному и тому же открытому ключу, соответствующему закрытому ключу, с помощью которого был подписан токен.

4. О, замечательно, я не знала! Я постараюсь в ближайшее время

5. Он имеет в виду, что это options.SaveToken не должно быть правдой. 🙂 Это делает его надлежащим токеном «на предъявителя» (что означает, что он действует как ключ, без необходимости существования токена на стороне сервера). Конечно, еще одним требованием является создание токенов с одним и тем же ключом шифрования, по крайней мере, в разных экземплярах (но в сценариях с несколькими экземплярами лучше использовать централизованный орган, да).