Сообщение об ошибке
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-приложениях чаще всего виновата пустая строка: веб-сервер не передал PHP заголовок `Authorization`, и код подставил `''`. Токен, у которого остался префикс `Bearer `, состоит из 3 сегментов, но разбор не проходит на следующем шаге, обычно с сообщением «Unexpected control character found» от JSON-декодера.
Почему это происходит
Заголовок Authorization не дошёл до PHP
частоApache с PHP-FPM или CGI отбрасывает `Authorization`, если передачу этого заголовка не включить явно; некоторые панели хостинга делают то же самое. Клиент отправляет заголовок, но `$_SERVER['HTTP_AUTHORIZATION']` не задан.
Значение — не JWT
частоИдентификатор сессии, непрозрачный токен доступа OAuth, API-ключ или `"null"`, отправленный JavaScript-клиентом, у которого ещё не было токена.
В строке остались схема или кавычки
иногдаЕсли передать всё значение заголовка или токен в 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+) или правило rewrite делает `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}]