Три токена, три задачи
После того как поток кода авторизации завершается (см. статью поток кода), клиент может в итоге держать три разных токена, и их смешение — одна из самых частых ошибок в и OpenID Connect. Токен доступа, токен обновления и ID-токен поверхностно похожи, особенно когда все три оказываются , но у них разные аудитории и разные цели. Попасть в цель с ними — это в основном вопрос того, чтобы для каждого токена спросить, для кого он и что он авторизует.
Токен доступа: ключ к API
Токен доступа — это то, что клиент отправляет серверу ресурсов (API), чтобы доказать, что ему позволено сделать запрос. Это самое близкое, что есть у OAuth к ключу сессии для доступа машина-машине, определено OAuth 2.0 (RFC 6749). Важны два свойства. Он короткоживущий, часто от минут до часа, чтобы утёкший токен был полезен лишь недолго. И это bearer-токен (предъявительский): кто его держит, может им пользоваться, без дальнейшего доказательства идентичности, и поэтому токены доступа должны путешествовать только по TLS и никогда не логироваться и не помещаться в URL. API проверяет токен и области, которые он несёт, а затем обслуживает или отклоняет запрос.
Токен обновления: получение новых токенов доступа
Поскольку токены доступа быстро истекают, заставлять пользователя входить заново каждые несколько минут было бы невыносимо. Токен обновления решает это: это долгоживущее удостоверение, которое клиент обменивает на сервере авторизации на свежий токен доступа, без взаимодействия пользователя. Он гораздо чувствительнее токена доступа именно потому, что долгоживущий, так что он должен оставаться на тыловом канале (на стороне сервера или в защищённом хранилище) и никогда не выставляться браузерному фронтенду. Хорошая практика — ротация токена обновления: каждое использование выпускает новый токен обновления и аннулирует старый, так что украденный токен обнаруживается в тот момент, когда легитимный клиент пытается использовать теперь отозванную копию. Токены также можно явно отозвать (RFC 7009).
ID-токен: заявление о пользователе
ID-токен — это часть, которую OpenID Connect добавляет поверх OAuth, и именно её чаще всего используют неправильно. Это всегда JWT (см. статью анатомия JWT), и он описывает событие аутентификации: кто пользователь, когда он аутентифицировался и какой сервер авторизации за это ручается. Критически важно: ID-токен для клиента, а не для API. Он отвечает на «кто только что вошёл», чтобы приложение могло установить сессию пользователя. Отправить ID-токен серверу ресурсов, как если бы он был токеном доступа, — классический баг: API должен его отклонить, потому что аудитория ID-токена — клиент, и использование его для авторизации путает идентичность с разрешением.
Bearer-токены и соблазн им доверять
Большинство токенов доступа — bearer-токены, что делает их лёгкими в использовании и лёгкими в злоупотреблении. Правила обращения вытекают напрямую: всегда TLS, короткие сроки жизни, никогда в логах или строках запроса, и никогда в доступном браузеру хранилище, если есть более защищённый вариант. Где модель bearer слишком рискованна, токены привязанные к отправителю (sender-constrained) связывают токен с конкретным ключом клиента (механизмы вроде DPoP или взаимного TLS), так что украденный токен не может быть воспроизведён кем-то ещё. Для большинства приложений короткоживущие bearer-токены доступа по TLS — рабочая основа.
Непрозрачные против JWT токены доступа
Токен доступа может быть непрозрачным (случайная строка, которую API проверяет, вызывая эндпоинт интроспекции сервера авторизации, RFC 7662) или JWT, который API проверяет сам. Форма JWT самодостаточна и избегает сетевого пути туда-обратно, но не может быть отозвана до истечения, что ещё одна причина держать сроки жизни токенов доступа короткими. ID-токен, напротив, всегда JWT, потому что вся его задача — донести проверяемые claims клиенту. То, является ли токен JWT, говорит вам, как он проверяется, а не для чего он.
Сопоставьте токен с аудиторией
Единственное правило, предотвращающее большинство багов токенов, — сопоставить каждый токен с его предполагаемой аудиторией. ID-токен для приложения, чтобы узнать, кто вошёл. Токен доступа для API, чтобы авторизовать запрос. Токен обновления для сервера авторизации, чтобы чеканить новые токены доступа, не беспокоя пользователя. Держите эти три аудитории раздельно, держите долгоживущий токен обновления на тыловом канале и относитесь к каждому bearer-токену как к короткоживущему секрету, и остальное в обращении OAuth с токенами встанет на место.