Создаю онлайн-сервис для чтения книг. День 5. JWT, Refresh, Access
Термины в статье:
🚀 Изменения в БД:
Для поддержки доступа к сайту с нескольких устройств (веб, десктоп, мобильное приложение) в таблицу UserSessions были добавлены следующие столбцы:
device_type : Тип устройства (web, desktop, mobile)
created_at : Дата создания сессии
🛠️ Изменения в коде:
1. Удаление флага bool Flag
Ранее в ответах сервера использовался флаг bool Flag для обозначения успешности операции. Теперь обработка ошибок выполняется через блоки try-catch. Это делает код более читаемым и устойчивым к ошибкам.
🐣 Реализация JWT-токенов
В файл конфигурации appsettings.json добавлен новый раздел JwtSection, содержащий секретный ключ и время жизни токена:
Для удобства работы с JWT был создан вспомогательный класс, который хранит данные из раздела JwtSection.
В Program.cs этот класс подключается следующим образом:
builder.Services.Configure<JwtSection>(builder.Configuration.GetSection("JwtSection"));
Был создан интерфейс, описывающий логику работы с базой данных для управления сессиями.
Реализую данный интерфейс. 💻
🔑 Генерация токенов:
Для генерации refresh-токена используется метод, который создает случайную строку из 32 байт:
Для генерации access-токена необходимы данные о пользователе (claims), секретный ключ из appsettings.json и срок действия токена:
🔒 Метод SignIn:
В методе SignIn происходит следующее:
Генерируются Access и Refresh токены.
Проверяется наличие сессии в базе данных. Если сессия существует, обновляется Refresh-токен.
Если сессия не найдена, создается новая запись в таблице UserSessions.
Обновление токенов 🔄
Если срок действия Access-токена истек, пользователь может получить новый токен, используя Refresh-токен. Для этого реализован метод RefreshToken:
Здесь происходят базовые проверки, во избежание ошибок. Далее генерируется новый Access-токен. Если срок Refresh-токена истек, то генерирую новый и отправляю его пользователю вместе с Access-токеном.
Защита эндпоинтов 🛡️
Для защиты эндпоинтов от неавторизованных пользователей была добавлена логика обработки Access-токенов:
Здесь из appsettings.json достаются все данные из ячейки JwtSection и помещаются в переменную config. Это позволяет централизованно управлять секретным ключом и временем жизни токена.
Далее добавляется аутентификация, указывая схему аутентификации (JwtBearer) в качестве параметра. Для этого используется метод AddJwtBearer, который как раз и будет валидировать токен. В нем указываются следующие проверки:
Срок жизни токена : Убедиться, что токен не истек. ⏳
Ключ шифрования : Проверить, что токен был подписан с использованием корректного секретного ключа. 🔑
В Program.cs регистрируется метод AddAuth:
builder.Services.AddAuth(builder.Configuration);
Также добавлены строки для использования аутентификации и авторизации
app.UseAuthentication();
app.UseAuthorization();
Теперь необходимо защитить Endpoint. Защищенные эндпоинты помечаются атрибутом [Authorize]:
Проверка работоспособности ▶️
Регистрация нового аккаунта 🆕
Регистрация проходит успешно, если данные пользователя уникальны.
Авторизация 🔑
После входа в систему пользователь получает Access и Refresh токены.
Проверка токена на jwt.io 🔍
На сайте jwt.io можно проверить содержимое Access-токена. В поле Payload видны все Claims.
Обращение к защищенному эндпоинту без токена 🚫
Получен статус-код 401, что означает "Доступ запрещен".
Обращение с токеном ✅
После добавления токена в заголовок Authorization запрос выполнен успешно (статус-код 200).
Заключение 🎉
Все компоненты системы аутентификации и управления сессиями работают корректно. Далее буду крудошлепить остальную бизнес-логику по аналогии.
🥁 А темой для следующей статьи станет:
Подтверждение почты через отправку кода в письме