Error message
Not enough or too many segments
Also printed as
- Not enough or too many segments (JWT::DecodeError)
- Invalid base64 encoding (JWT::Base64DecodeError)
ruby-jwt 2.x raised `JWT::DecodeError` with the same text. The `Bearer` prefix case gives "Invalid base64 encoding (JWT::Base64DecodeError)".
ruby-jwt (Ruby) — JWT::DecodeError (JWT::MalformedTokenError in 3.x) from JWT.decode
What it means
ruby-jwt split the input on dots and did not find the three segments of a signed JWT, so nothing else was checked. In ruby-jwt 3.x the class is `JWT::MalformedTokenError` (a `JWT::TokenError`, which is a `JWT::DecodeError`), so existing `rescue JWT::DecodeError` blocks still catch it. A token that still has its `Bearer ` prefix splits into three parts but fails on the first one with "Invalid base64 encoding" instead.
Why it happens
An empty or non-JWT value
commonA missing header turned into `""` by `to_s`, a session cookie, or an opaque OAuth access token that was never a JWT.
The Authorization header was decoded whole
common`request.headers["Authorization"]` returns `Bearer eyJ…`. Strip the scheme before decoding.
An encrypted token
rareFive-segment JWE tokens are not supported by `JWT.decode`; they must be decrypted with a JWE library first.
How to fix it
- 1.
Extract and shape-check the token first
Accept only `Bearer <header.payload.signature>` and respond 401 for anything else, before ruby-jwt sees it.
ruby def bearer_token(request) scheme, token = request.authorization.to_s.split(" ", 2) return nil unless scheme&.casecmp?("Bearer") && token&.count(".") == 2 token end token = bearer_token(request) or return head(:unauthorized) payload, _header = JWT.decode(token, public_key, true, algorithm: "ES256")