UNIT ID

Токены и id_token

Сколько живут токены, как устроен id_token и как его проверить.

Сроки жизни

ЧтоСрокОсобенности
Код авторизации60 секундОдноразовый: повторный обмен — invalid_grant.
access_token1 часНепрозрачная строка — не разбирайте её, отправляйте как есть.
refresh_token30 днейОдноразовый: каждое обновление выдаёт новый.
id_token1 часПроверяется по ключам JWKS; для входа достаточно проверить один раз.

Токен может перестать действовать раньше срока: человек отозвал доступ приложению или вышел на устройстве, где разрешал вход; сменил пароль или включил 2FA (это выход на остальных устройствах); администратор отключил аккаунт. Ответ 401 от API или invalid_grant при обновлении означает одно — попросите человека войти заново.

Что внутри id_token

id_token — JWT, подписанный RS256. Заголовок содержит kid — ключ, которым подписан токен.

{
  "iss": "https://auth.labunit.ru",
  "sub": "s-4kq9tz",
  "aud": "unit-0123456789abcdef",
  "iat": 1791800000,
  "exp": 1791803600,
  "nonce": "…",                // если передавали в запросе
  "name": "Анна Смирнова",    // profile
  "preferred_username": "anna",
  "unit_roles": ["student"],
  "unit_tags": ["школа", "ученик"],
  "email": "anna@labunit.ru", // email
  "email_verified": true
}

Проверка

  1. Возьмите ключ с совпадающим kid из https://auth.labunit.ru/oauth/jwks. Ключи можно кешировать; если kid не нашёлся — перечитайте JWKS.
  2. Проверьте подпись алгоритмом RS256. Другие алгоритмы (особенно none и HS256) не принимайте.
  3. iss равен https://auth.labunit.ru, aud — вашему client_id.
  4. exp в будущем (допуск на расхождение часов — минута-две).
  5. Если передавали nonce — он совпадает с сохранённым.
Python · PyJWT
import jwt  # pip install pyjwt[crypto]

jwks = jwt.PyJWKClient("https://auth.labunit.ru/oauth/jwks")
key = jwks.get_signing_key_from_jwt(id_token).key
claims = jwt.decode(id_token, key, algorithms=["RS256"],
                    audience=CLIENT_ID, issuer="https://auth.labunit.ru", leeway=60)
user_id = claims["sub"]
Node.js · jose
import { createRemoteJWKSet, jwtVerify } from "jose";

const jwks = createRemoteJWKSet(new URL("https://auth.labunit.ru/oauth/jwks"));
const { payload } = await jwtVerify(idToken, jwks, {
  issuer: "https://auth.labunit.ru", audience: CLIENT_ID, algorithms: ["RS256"],
});

Если вы получили id_token напрямую от /oauth/token по HTTPS со своего сервера, его можно считать подлинным и без проверки подписи. Проверка обязательна, когда токен попадает к вам через браузер или от другого сервиса.

UNIT · UNIT ID · вопросы по интеграции — администратору UNIT