エラーメッセージ
Wrong number of segments
別の表記
- UnexpectedValueException: Wrong number of segments
- Unexpected control character found
出力されるときは、先頭にクラス名が付きます(「UnexpectedValueException: Wrong number of segments」)。`Bearer` の接頭辞が残っている場合は、代わりに「Unexpected control character found」(`DomainException`)が発生します。
firebase/php-jwt (PHP) — UnexpectedValueException from JWT::decode
このエラーの意味
`JWT::decode` は入力をドットで分割しましたが、ちょうど 3 つの部分にはなりませんでした。そのため、入力はコンパクト形式の JWS ではなく、ほかのチェックは何も行われていません。PHP アプリケーションで最もよくある原因は空文字列です。Web サーバーが `Authorization` ヘッダーを PHP に渡さず、コードが `''` にフォールバックしています。`Bearer ` の接頭辞が残ったままのトークンは 3 つのセグメントを持ちますが、1 段階後で失敗し、通常は JSON デコーダーから「Unexpected control character found」が出ます。
発生する理由
Authorization ヘッダーが PHP に届いていない
よくあるPHP-FPM や CGI と組み合わせた Apache は、渡すように設定しない限り `Authorization` を取り除きます。一部のホスティングのコントロールパネルも同様です。クライアントはヘッダーを送信していますが、`$_SERVER['HTTP_AUTHORIZATION']` は設定されていません。
値が JWT ではない
よくあるセッション ID、不透明な OAuth アクセストークン、API キー、まだトークンを持っていない JavaScript クライアントが送った `"null"` などが該当します。
文字列にスキームや引用符が残っている
ときどきヘッダーの値全体や、引用符付きの JSON エンコードされたトークンを渡すと、最初のセグメントのパースが失敗します。
修正方法
- 1.
ヘッダーを確実に読み取り、形式を検証する
サーバー構成によって異なるヘッダーの格納場所を確認し、`Bearer <three base64url segments>` だけを受け付けて、それ以外には 401 で応答してください。
php function bearerToken(): ?string { $header = $_SERVER['HTTP_AUTHORIZATION'] ?? $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] // Apache + mod_rewrite ?? (function_exists('apache_request_headers') ? (apache_request_headers()['Authorization'] ?? '') : ''); if (!preg_match('/^Bearer\s+([A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]*)$/', $header, $m)) { return null; } return $m[1]; } - 2.
Apache がヘッダーを渡すように設定する
`CGIPassAuth On`(Apache 2.4.13 以降)または書き換えルールを使うと、`Authorization` を PHP から参照できるようになります。
text # Apache with PHP-FPM / CGI: pass the Authorization header through CGIPassAuth On # or, with mod_rewrite: RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]