エラーメッセージ
Not enough or too many segments
別の表記
- Not enough or too many segments (JWT::DecodeError)
- Invalid base64 encoding (JWT::Base64DecodeError)
ruby-jwt 2.x では、同じテキストで `JWT::DecodeError` が発生していました。`Bearer` プレフィックスが付いている場合は「Invalid base64 encoding (JWT::Base64DecodeError)」になります。
ruby-jwt (Ruby) — JWT::DecodeError (JWT::MalformedTokenError in 3.x) from JWT.decode
このエラーの意味
ruby-jwt は入力をドットで分割しましたが、署名付き JWT の 3 つのセグメントが見つからなかったため、それ以外のチェックは行われていません。ruby-jwt 3.x ではクラスは `JWT::MalformedTokenError` です。これは `JWT::TokenError` のサブクラスで、その親クラスが `JWT::DecodeError` なので、既存の `rescue JWT::DecodeError` ブロックで引き続き捕捉できます。`Bearer ` プレフィックスが付いたままのトークンは 3 つに分割されますが、代わりに最初の部分で「Invalid base64 encoding」として失敗します。
発生する理由
空の値、または JWT 以外の値
よくある存在しないヘッダーが `to_s` によって `""` になったもの、セッション Cookie、またはそもそも JWT ではなかった不透明な OAuth のアクセストークンです。
Authorization ヘッダーを丸ごとデコードした
よくある`request.headers["Authorization"]` は `Bearer eyJ…` を返します。デコードの前にスキームを取り除いてください。
暗号化されたトークン
まれ5 つのセグメントからなる JWE トークンは `JWT.decode` ではサポートされていません。先に JWE ライブラリで復号する必要があります。
修正方法
- 1.
先にトークンを取り出して形式を確認する
ruby-jwt に渡す前に、`Bearer <header.payload.signature>` の形式だけを受け入れ、それ以外には 401 を返してください。
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")