Перейти к содержимому
ecdsa.com
golang-jwt/jwt (Go)Go

Сообщение об ошибке

token has invalid claims: token is expired

Также выводится как

  • Token is expired
  • token has invalid claims: token is not valid yet
  • token has invalid claims: token used before issued

golang-jwt v4 выводит «Token is expired» (с заглавной T). Остальные ошибки утверждений в v5 используют тот же префикс «token has invalid claims:».

golang-jwt/jwt (Go) — jwt.ErrTokenInvalidClaims joined with jwt.ErrTokenExpired

Что это означает

Подпись токена прошла проверку, но его утверждение `exp` указывает на прошлое (даже с учётом настроенного допуска, если он есть). golang-jwt v5 сообщает об этом как о `ErrTokenInvalidClaims`, объединённой с `ErrTokenExpired`; то же семейство ошибок выдаёт «token is not valid yet» для `nbf` в будущем и «token used before issued» для `iat` в будущем. Разобранный токен всё равно возвращается вместе с ошибкой, но доверять ему нельзя.

Почему это происходит

Как исправить

  1. 1.

    Распознавайте истечение срока действия и давайте клиенту обновить токен

    Отвечайте на `ErrTokenExpired` кодом 401 с подсказкой `invalid_token`. Тогда клиент воспользуется токеном обновления (или пройдёт аутентификацию заново) и повторит запрос.

    go
    token, err := jwt.Parse(raw, keyfunc, jwt.WithValidMethods([]string{"ES256"}))
    if errors.Is(err, jwt.ErrTokenExpired) {
    	w.Header().Set("WWW-Authenticate", `Bearer error="invalid_token", error_description="token expired"`)
    	http.Error(w, "token expired", http.StatusUnauthorized) // client refreshes and retries
    	return
    }
  2. 2.

    Допускайте небольшое расхождение часов, требуйте exp

    Допуск в несколько секунд компенсирует расхождение часов между машинами. `WithExpirationRequired` закрывает противоположную брешь: иначе токены без `exp` никогда не истекали бы.

    go
    parser := jwt.NewParser(
    	jwt.WithValidMethods([]string{"ES256"}),
    	jwt.WithLeeway(30*time.Second), // absorbs clock skew for exp, nbf and iat
    	jwt.WithExpirationRequired(),   // tokens without exp are rejected too
    )

Связанные ошибки

Открыть всю базу ошибок подписей