Передается ли JWT в зашифрованном или открытом виде
Что проверяют
Отличаете ли вы подпись от шифрования. Вопрос короткий, но по ответу видно, понимает ли кандидат, что base64url это кодирование, а не защита, и знает ли, как в Go правильно разобрать токен. Заодно смотрят, что вы вообще кладёте в полезную нагрузку.
Как отвечать
Обычный JWT это JWS: три части через точку, заголовок и полезная нагрузка закодированы base64url и читаются кем угодно без ключа. Подпись даёт целостность и подлинность, но не конфиденциальность. Скрыть содержимое умеет JWE, на практике его берут редко: дешевле возить токен только по TLS и не класть внутрь ничего чувствительного, кроме идентификатора пользователя, ролей и срока жизни.
В Go разбор обязан проверять алгоритм, иначе проверка подписи теряет смысл:
tok, err := jwt.ParseWithClaims(raw, &Claims{}, func(t *jwt.Token) (any, error) {
if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("неожиданный алгоритм")
}
return secret, nil
})Дальше стоит назвать проверку exp, iss, aud, короткий срок access-токена, refresh в httpOnly cookie и то, что токен в параметре URL оседает в логах прокси и в заголовке Referer, поэтому ему место в заголовке Authorization.
Где спотыкаются
Называют base64 шифрованием и кладут в нагрузку персональные данные, внутренние идентификаторы, иногда телефон и почту. Любой, кто получил токен, читает это в первом попавшемся декодере, ключ для этого не нужен.
Второе: возвращают ключ из keyfunc, не посмотрев на заголовок alg. Отсюда две классические атаки: подмена алгоритма на none и переключение с RS256 на HS256, когда публичный ключ сервера подсовывается как секрет HMAC.
Третье: считают, что подписанный токен можно отозвать. Он действителен до exp, сервер о нём ничего не хранит. Нужен короткий срок жизни, список отозванных jti или версия сессии внутри claims, иначе кнопка выхода из всех устройств ничего не делает.