Сообщение об ошибке
token is malformed: token contains an invalid number of segments
Также выводится как
- token is malformed: could not base64 decode header: illegal base64 data at input byte 6
- token contains an invalid number of segments
v5 добавляет префикс «token is malformed: ». v4 выводит только внутренний текст, например «token contains an invalid number of segments». Смещение в байтах в «illegal base64 data at input byte N» указывает на первый некорректный символ.
golang-jwt/jwt (Go) — jwt.ErrTokenMalformed
Что это означает
golang-jwt не смог даже прочитать структуру токена. «invalid number of segments» означает, что в строке не ровно две точки; «could not base64 decode header» означает, что первый сегмент — не base64url, чаще всего потому, что к токену всё ещё приклеен префикс `Bearer ` (байт 6 — пробел). В v5 эти ошибки обёрнуты в `jwt.ErrTokenMalformed`; поиск ключа не выполнялся.
Почему это происходит
Заголовок Authorization разобран целиком
часто`r.Header.Get("Authorization")` возвращает `Bearer eyJ…`. Если передать это значение прямо в `jwt.Parse`, из-за пробела сегмент заголовка становится некорректным base64.
Значение — не JWT
частоВ парсер попадают непрозрачные токены доступа OAuth, идентификаторы сессий, API-ключи или пустой заголовок. JWS-токены — только строки из трёх сегментов base64url.
Зашифрованный токен (JWE) из пяти сегментов
иногдаНекоторые поставщики удостоверений шифруют токены. golang-jwt работает только с подписанными токенами; сначала расшифруйте JWE (например, с помощью go-jose), а затем разберите вложенный JWS.
Токен обрезан
иногдаТокен обрезали столбец базы данных, ограничение размера cookie (4 КБ) или строка журнала, и последний сегмент или точка пропали.
Как исправить
- 1.
Извлекайте токен с помощью пакета request
`github.com/golang-jwt/jwt/v5/request` отбрасывает схему `Bearer` без учёта регистра и возвращает `request.ErrNoTokenInRequest`, если токена нет вовсе.
go import "github.com/golang-jwt/jwt/v5/request" token, err := request.ParseFromRequest(r, request.OAuth2Extractor, keyfunc, request.WithParser(jwt.NewParser(jwt.WithValidMethods([]string{"ES256"})))) if err != nil { http.Error(w, "unauthorized", http.StatusUnauthorized) return } - 2.
Проверяйте форму токена до разбора
Подсчёт точек отличает JWS (2), JWE (4) и мусор. Отвечайте 401 на всё, кроме токенов, которые вы умеете обрабатывать.
go raw := strings.TrimSpace(strings.TrimPrefix(r.Header.Get("Authorization"), "Bearer ")) switch strings.Count(raw, ".") { case 2: // JWS: parse it case 4: // JWE: decrypt first (go-jose), golang-jwt does not handle encrypted tokens default: http.Error(w, "unauthorized", http.StatusUnauthorized) return }