Как получить jwt токен внутри метода с атрибутом AllowAnonymous?

Ссылка скопирована
1 ответ

Если для доступа к эндпоинту требуется авторизация через заголовок в котором указывается jwt токен доступа, то я могу спокойно получить его значение и обратиться к Claims где хранится id пользователя

var userId = context.HttpContext.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value; var token = await HttpContext.GetTokenAsync(JwtBearerDefaults.AuthenticationScheme, "access_token")

var userId = context.HttpContext.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value; var token = await HttpContext.GetTokenAsync(JwtBearerDefaults.AuthenticationScheme, "access_token")

Но в методе с атрибутом AllowAnonymous все будет null

Дополнительно:

А зачем получать id пользователя в методе, не требующем идентификации пользователя?

  • Rsa97, У меня есть эндпоинт refresh, к нему клиент обращается когда эндпоинты, которые требуют токен доступа, возвращают статус код 401 и клиент запрашивает refresh, у токена доступа в Claims записан id пользователя, я его беру и из бд извлекаю refresh token пользователя. Не буду полностью расписывать принцип работы этого эндпоинта, но суть должна быть ясна
  • Dudder, А что мешает записать id пользователя в refresh-токен и не ставить AllowAnonymous?
  • Rsa97, 1. Это мне нужно извлекать из каждой записи в бд строку refresh token, брать из нее Claims и извлекать id, не знаю на сколько это будет нагружать бд. 2. Эндпоинт все равно будет AllowAnonymous, так как он вызывается только тогда, когда токен доступа просрочен. С атрибутом Authorize он не будет выполняться при просроченном токене
  • Dudder, Зачем? Refresh-токен это такой-же JWT, только в нём немного другая информация, как правило только uid токена и id пользователя.
  • Я немного не понял, как я узнаю id пользователя который обращается к refresh?
  • Rsa97, Объясните немного подробнее Ваш подход, пожалуйста
  • Dudder, Вы знаете, что такое JWT? Это структура из трёх частей - заголовка, полезной нагрузки и подписи. Так в полезную нагрузку можно вписать что угодно.
    В качестве refresh-токена чаще всего используется тот же JWT, только в полезной нагрузке у него минимальная информация, достаточная для выдачи новой пары токенов. Обычно это uid токена и id пользователя. Uid используется для проверки, что по данному токену ещё никто не обновлялся.
  • то я могу спокойно получить его значение и обратиться к Claims где хранится id пользователя

    и что вам это дает? если вы не владелец системы... id пользотвалея не дает вам досутпа ни к чему, а еще это может быть открытая информация, например email

  • Dudder, вообще то, токен надо обновлять до его истечения.
  • Dudder, когда клиенты с истекшим АТ получили 401, это значит что авторизация не прошла - и в методе с AllowAnonymous, если вы передаете токен, Identity.IsAuthenticated тоже будет false у юзера, т.к. время жизни токена истекло.
    Как я поступал в подобной ситуации: на RefreshUrl отправляем модель с AT и RT, плюсом один из клеймов AT - SessionId.
    Для разбора AT написан свой хелпер, который создает JwtTokenHandler с настройками, идентичными AddAuthentication, но с отключенной проверкой времени жизни токена.
    В данной схеме RT - не JWT, а просто уникальный идентификатор, который при рефреше меняется - чтобы не получить два рабочих AT на сессию.

    Как вариант можно сложить все нужные клеймы в RT (тоже JWT), тогда отправлять AT клиенты не должны вовсе, но свой TokenHandler для разбора RT и извлечения клеймов вам все равно понадобится.

  • Роман, поясните мысль, пожалуйста. Например в ситуации, когда клиент не делал запросов за период времени ATLifetime < Tau < RTLifetime (человек не обновлял страницу, не нажимал кнопок и т.п.), как тогда следует поступать?
  • Лично у нас сделано так, что Refresh живет независимо от JWT, JWT живет как правило несколько минут, а Refresh может жить хоть год. Поэтому у нас сделано так, что после недели неактивности можно по Refresh'y взять новый JWT и продолжать работать. Refresh'и держим в базе, при попытке обновить JWT по Refresh'y - смотрим в базу и строим новый JWT. Имхо, но нет смысла держать в Refresh'e данные, т.к. за время жизни JWT и Refresh'a могут поменяться данные человека, в т.ч. роли, имя, почта и прочее, иногда эти данные нужны в JWT.
    Поэтому вам не обязательно получать никакие данные от пользователя, достаточно сам Refresh token, а по нему в базе посмотреть кто его запрашивает и выдать новый JWT. (ИМХО(!))
  • OwDafuq, У меня буквально так и реализовано, в refresh хранится только id пользователя
  • Dudder, если честно - не понимаю зачем в нем что-то хранить в целом, время жизни у Refresh'a тоже должно быть время жизни, в базу полезете всё равно, а там можно и связь на таблицу пользователей сделать
  • Нужно решить такую задачу?

    Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

    Заказать помощь
    Лучший ответ
    1
    Роман IT Ответ

    Для того чтобы получить JWT токен внутри метода с атрибутом AllowAnonymous, вам потребуется использовать библиотеку для работы с JWT токенами в вашем проекте. Например, вы можете воспользоваться библиотекой System.IdentityModel.Tokens.Jwt для работы с JWT токенами в .NET.

    Вот пример кода на языке программирования C#, который показывает, как получить JWT токен внутри метода с атрибутом AllowAnonymous:

    using System.IdentityModel.Tokens.Jwt;
     
    public class AuthController : ControllerBase
    {
        [AllowAnonymous]
        [HttpPost("login")]
        public IActionResult Login([FromBody] LoginModel model)
        {
            // Проверяем учетные данные пользователя
            if (ValidateUser(model.Username, model.Password))
            {
                // Генерируем JWT токен
                var token = GenerateJwtToken(model.Username);
     
                return Ok(new { token });
            }
     
            return Unauthorized();
        }
     
        private string GenerateJwtToken(string username)
        {
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your_secret_key_here"));
            var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
     
            var token = new JwtSecurityToken(
                issuer: "your_issuer_here",
                audience: "your_audience_here",
                claims: new[] { new Claim(ClaimTypes.Name, username) },
                expires: DateTime.Now.AddHours(1),
                signingCredentials: credentials
            );
     
            return new JwtSecurityTokenHandler().WriteToken(token);
        }
    }

    using System.IdentityModel.Tokens.Jwt; public class AuthController : ControllerBase { [AllowAnonymous] [HttpPost("login")] public IActionResult Login([FromBody] LoginModel model) { // Проверяем учетные данные пользователя if (ValidateUser(model.Username, model.Password)) { // Генерируем JWT токен var token = GenerateJwtToken(model.Username); return Ok(new { token }); } return Unauthorized(); } private string GenerateJwtToken(string username) { var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your_secret_key_here")); var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken( issuer: "your_issuer_here", audience: "your_audience_here", claims: new[] { new Claim(ClaimTypes.Name, username) }, expires: DateTime.Now.AddHours(1), signingCredentials: credentials ); return new JwtSecurityTokenHandler().WriteToken(token); } }

    В данном примере метод Login помечен атрибутом AllowAnonymous, что позволяет вызывать его без аутентификации. Внутри метода мы сначала проверяем учетные данные пользователя, а затем генерируем JWT токен с помощью метода GenerateJwtToken. В этом методе мы используем секретный ключ для подписи токена и создаем JWT токен с истекающим сроком действия.

    Не забудьте заменить "your_secret_key_here", "your_issuer_here" и "your_audience_here" на ваши собственные значения. Также обратите внимание, что безопасное хранение и обработка секретного ключа крайне важны для защиты ваших JWT токенов.

    Другие ответы (0)

    Пока нет других ответов. Будьте первым, кто поможет автору.

    Ответить на вопрос

    комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *

    Вам также может быть интересно