Разговор про аутентификацию при помощи JWT будет не полным если не упомянуть еще один токен – Refresh Token. Цель данной статьи понять зачем он нужен и каким образом используется. |
А в чем проблема с JWT?
Для начала рассмотрим как могут взаимодействовать клиентское приложение, ресурс, к которому нужно получить доступ с использованием JWT, и сервер аутентификации (как внешний, как и часть системы, где расположен ресурс) .
- Клиентское приложение аутентифицируется на сервере аутентификации, передавая ему имя и пароль пользователя.
- В ответ сервис аутентификации передает клиентскому приложению JWT для доступа к ресурсу.
- Клиентское приложение использует JWT для доступа к ресурсу.
- После момента времени, заданного в утверждении exp, JWT становится устаревшим.
- При следующем обращении ресурс выдает ошибку аутентификации из-за устаревшего JWT.
- Теперь клиентскому приложению необходимо получить новый JWT. Переходим к шагу 1 и повторяем все заново.
Что в этой схеме не так? Сложно определить оптимальный срок жизни JWT.
Если его задать небольшим, то пользователю придется постоянно проходить аутентификацию. А кому понравится вводить свои данные, например, каждые 5 или даже пусть 30 минут? Можно конечно предложить хранить имя пользователя и пароль в приложении. Но, в первую очередь, это не безопасно. Более того, если для аутентификации используется внешний сервис (например, какая-нибудь социальная сеть), то приложение вообще может не иметь доступа к используемым там имени и паролю.
Решением может показаться возможность сильно увеличить exp (время жизни JWT). Например, установить его на следующие сутки, неделю или еще больше. Однако, в этом случае, клиентское приложение будет иметь доступ до ресурса, даже если данные пользователя поменяются (например, пароль, права доступа, если они передаются с сервера, и т.д.). Также это открывает возможности для взлома приложения. Например, если JWT был перехвачен злоумышленником, то он сможет его использовать до истечения срока жизни JWT. И даже смена пароля пользователем не поможет устранить эту ситуацию.
Refresh Token
Решением описанной выше проблемы является добавление в процесс аутентификации еще одного токена - Refresh Token (токен обновления). Он предназначен исключительно для получения нового JWT и, в отличии от последнего, сохраняется на сервере аутентификации и имеет большой срок жизни.
Refresh Token позволяет установить небольшое время жизни JWT. Но при этом пользователю не нужно будет проходить постоянную аутентификацию.
По сути время жизни Refresh Token это время, через которое пользователю придется пройти обязательно повторную ау��ентификацию.
С Refresh Token схема взаимодействия изменится следующим образом:
- Клиентское приложение аутентифицируется на сервере аутентификации, передавая ему имя и пароль пользователя.
- В ответ сервис аутентификации передает клиентскому приложению JWT для доступа к ресурсу и Refresh Token.
- Клиентское приложение использует JWT для доступа к ресурсу.
- После момента времени, заданного в утверждении exp, JWT становится устаревшим.
- При следующем обращении ресурс выдает ошибку аутентификации из-за устаревшего JWT.
- Клиентское приложение обращается к серверу аутентификации с использованием Refresh Token для получения нового JWT.
- Если Refresh Token валидный, то клиентское приложение получит новый JWT и новый Refresh Token для следующего обновления JWT.
- Если Refresh Token не валидный, то клиентскому приложению придется пройти аутентификацию заново.
Refresh Token может стать не валидным не только по истечению времени его жизни. Другими возможными причинами могут быть:
- Смена пароля пользователем.
- Подозрение в "утечке" Refresh Token или JWT.
- Если Refresh Token связан с конкретным приложением или даже его экземпляром, то отказ в доступе этому приложению (экземпляру). Например, социальные сети дают пользователю возможность удалять приложения, которые используют их для аутентификации пользователя.
Например, если сервер аутентификации предоставляет некие данные о пользователе (например, права доступа, имя, email и т.д.), то нет необходимости передавать их в JWT как утверждения. Как минимум, это может сильно увеличить размер токена и нести некоторые риски безопасности при его перехвате злоумышленниками.
Достаточно добавить в JWT утверждение с абстрактным значением, которое будет изменяться при модификации профиля пользователя. А для получения самих данных предоставить специализированный API.
В следующей части рассмотрим пример реализации Refresh Token в ASP.NET Core приложении.