Вопрос или проблема
Я использую JWT для аутентификации пользователей в моих мобильных и веб-приложениях в одном API. И access_token, и refresh_token имеют одинаковый срок действия
Passport::tokensExpireIn(now()->addHours(1));
Passport::refreshTokensExpireIn(now()->addHours(1));
Когда пользователь входит в систему
- аутентификация (имя пользователя и пароль), сохранение access token (на стороне клиента), в то время как refresh_token (я его вообще не использую)
- Если access_token истек, то это сразу приведет к повторной аутентификации (#1 повтор)
Мой вопрос: Поскольку срок действия будет длиться час и процесс достаточно безопасен, я что-то упускаю?
Я понимаю, как использовать refresh_token.
- Если access_token истек, то он будет использовать refresh_token, чтобы получить новый access_token + новый refresh_token. (требует id клиента и секретный ключ)
- Наличие refresh_token означает, что access_token истечет, и вы сможете получить новый даже без взаимодействия пользователя
- предназначен для автоматического обнаружения и предотвращения попыток использовать один и тот же refresh_token параллельно из разных приложений/устройств.
- снижает риск утечки длительного access_token (что в моем случае не актуально)
- Как только новый access_token + refresh_token будут сгенерированы с использованием refresh_token, предыдущие access_token и refresh_token станут бесполезными или будут отозваны
Мой вопрос: Должен ли я использовать refresh_token? Я подумываю сохранить его на бэкенде или сервере. Установить срок действия, который дольше, чем у access_token, который все еще 1 час, но для refresh_token сделать его 1 год, если не будет отозван. Как только аутентификация будет пройдена, это будет генерировать новый access_token с использованием refresh_token, отправляя новый access_token на стороне клиента, а затем снова сохраняя новый refresh_token на сервере и так далее. Это будет происходить каждый раз, когда он/она входит в систему или регистрируется. Вы считаете, что нормально хранить refresh_token на бэкенде?
Мне кажется, вы, возможно, путаете сценарий использования access token. Они не предназначены для аутентификации пользователей для вашего приложения; их цель – авторизовать клиентское приложение для работы с API ресурса от имени пользователя.
Если вы просто хотите аутентифицировать пользователя для ваших приложений, вам следует использовать id_token, предоставляемый OpenID Connect. id_token предназначен для предоставления вашим приложениям необходимых сведений (в виде JWT-требований) об аутентифицированном пользователе; это позволяет каждому из ваших приложений инициировать свои собственные сессии на основе этих требований. Таким образом, ваша сессия может быть такой длинной или короткой, как вам нужно – она независима от сессии пользователя в AS (или Провайдере OpenID, как это называется в терминологии OIDC).
Отозвать JWT крайне неудобно, не нарушая безгосударственности, которая является их основным преимуществом в контексте, не связанном с SSO. Таким образом, стандартная практика заключается в том, что JWT имеет очень короткий срок действия – обычно несколько минут – а refresh token хранится в базе данных (в виде хеша) и используется для повторной выдачи access token, когда он истекает. По существу, это гибридная система: при большинстве запросов вы получаете безгосударственность JWT, но refresh token (который может быть недействительным/отозванным) позволяет JWT быстро истечь, когда пользователь выходит из системы или его сессия иначе завершается, при затратах на один вызов БД.
Срок действия refresh token может быть любым, каким вы хотите. Час, год, век – в зависимости от того, хотите ли вы заставить людей снова входить в систему или нет. Вы также можете сделать его роллингом (насколько долго он используется, его срок действия продлевается), если хотите. Что касается того, когда обновлять JWT, вы можете сделать это автоматически с сервера, когда он истекает (если JWT истек, проверьте наличие действительного токена сессии для получения нового JWT), автоматически с клиента, когда JWT истекает (если сервер возвращает ошибку доступа, вызовите конечную точку обновления для получения нового JWT), или автоматически с клиента перед истечением JWT (используя скрипт для периодического обновления JWT за несколько секунд до истечения, пока страница открыта).
Ответ или решение
Использование только токена доступа (access token) для аутентификации и авторизации пользователей в веб и мобильных приложениях может вызвать опасения по поводу безопасности и управляемости сессиями. Рассмотрим подробнее, что подразумевается под токенами доступа и обновления, а также оценим ваши текущие практики.
Токены доступа и обновления: назначение и использование
Токен доступа (access token) чаще всего используется для предоставления клиенту (веб или мобильному приложению) временного доступа к защищенным ресурсам API от имени пользователя. Токен обновления (refresh token), в свою очередь, предназначен для генерации нового токена доступа без необходимости повторного входа пользователя в систему.
Причины, почему стоит использовать токен обновления
-
Безопасность и управление сессиями: Токены доступа, как правило, имеют короткий срок действия (в вашем случае – 1 час), что является хорошей практикой, поскольку это снижает риск компрометации токена. Однако, в случае, если для получения нового токена доступа не предусмотрено использования токена обновления, пользователю потребуется повторно вводить свои учетные данные (логин и пароль) в каждом случае истечения срока действия токена. Это может значительно ухудшить пользовательский опыт.
-
Управление доступом: Токены обновления позволяют более гибко управлять доступом. Например, если пользователь выходит из системы, сервер может отозвать токен обновления, тем самым автоматически аннулируя возможность получения нового токена доступа. Это значительно облегчает управление сессиями и повышает безопасность.
-
Минимизация затруднений при истечении токена доступа: Если токен обновления используется, приложение может автоматически получать новый токен доступа, как только старый истечет, что избавляет конечных пользователей от постоянного ввода паролей.
-
Сохранение состояния сессии: Когда токены обновления хранятся на стороне сервера (например, в базе данных), это дает возможность легко их отозвать или изменить в случае необходимости, например, при изменении пароля или недобросовестном поведении.
Рекомендации по использованию токена обновления
Если вы решите использовать токены обновления, вот несколько рекомендаций:
-
Срок действия токенов обновления: Вы можете установить срок действия долгосрочным, например 1 год, с возможностью отзыва по требованию. Это отключит пользователя при необходимости без повторной аутентификации до истечения срока действия, снижая риск уязвимости.
-
Хранение на сервере: Лучше всего хранить токены обновления на стороне сервера в зашифрованном виде. При этом токен обновления не будет доступен клиенту напрямую, что снижает риск его утечки.
-
Применение методологии rolling tokens: Это означает, что если токен обновления используется, его срок действия может быть продлен, что позволяет пользователю оставаться аутентифицированным, как долго они активны в системе.
Заключение
Использование только токена доступа может быть достаточно для простейших сценариев аутентификации, однако для обеспечения хорошего пользовательского опыта и повышения уровня безопасности настоятельно рекомендуется внедрить систему токенов обновления. Объединение короткоживущих токенов доступа с долгоживущими токенами обновления позволяет вам эффективно управлять сессиями пользователей и защищать API от потенциальных угроз.