thephpleague/oauth2-server · error · OAuthServerException

Missing "Authorization" header

Error message

Missing "Authorization" header

What it means

BearerTokenValidator::validateAuthorization() requires an HTTP Authorization header to authenticate the resource request. Without one it throws an access_denied error immediately, before any JWT parsing.

Solutions

  1. Send 'Authorization: Bearer <access_token>' on the request.
  2. Check proxies/CORS middleware aren't stripping the Authorization header.
  3. Confirm the request is hitting validateAuthorization only after authentication on the client side.

Example fix

// before
$response = $client->get('https://api.example.com/me');
// after
$response = $client->get('https://api.example.com/me', ['headers' => ['Authorization' => 'Bearer ' . $accessToken]]);
Defensive patterns

Strategy: validation

Validate before calling

if (!isset($_SERVER['HTTP_AUTHORIZATION']) && !isset(apache_request_headers()['Authorization'] ?? null)) {
    throw new \RuntimeException('Authorization header missing');
}

Try / catch

try { $request = $validator->validateAuthorization($request); } catch (OAuthServerException $e) { return $e->generateHttpResponse(new Response(), 401); }

Prevention

When it happens

Trigger: Calling validateAuthorization() on a PSR-7 request that has no Authorization header (anonymous request, or middleware ordering removed it).

Common situations: Frontend didn't attach the token; CORS preflight sent to protected route; reverse proxy strips Authorization header; client sends 'authorization' via query param instead.

Related errors


AI-assisted analysis of thephpleague/oauth2-server@9d2f6fc0a0 (2026-09-15). Data as JSON: /api/errors/8ac3363a2aaf0b13. Report an issue: GitHub.

Appendix: source

Thrown at src/AuthorizationValidators/BearerTokenValidator.php:99

        }

        // TODO: next major release: replace deprecated method and remove phpstan ignored error
        $this->jwtConfiguration->setValidationConstraints(
            new LooseValidAt($clock, $this->jwtValidAtDateLeeway),
            new SignedWith(
                new Sha256(),
                InMemory::plainText($publicKeyContents, $this->publicKey->getPassPhrase() ?? '')
            )
        );
    }

    /**
     * {@inheritdoc}
     */
    public function validateAuthorization(ServerRequestInterface $request): ServerRequestInterface
    {
        if ($request->hasHeader('authorization') === false) {
            throw OAuthServerException::accessDenied('Missing "Authorization" header');
        }

        $header = $request->getHeader('authorization');
        $jwt = trim((string) preg_replace('/^\s*Bearer\s/i', '', $header[0]));

        if ($jwt === '') {
            throw OAuthServerException::accessDenied('Missing "Bearer" token');
        }

        try {
            // Attempt to parse the JWT
            $token = $this->jwtConfiguration->parser()->parse($jwt);
        } catch (Exception $exception) {
            throw OAuthServerException::accessDenied($exception->getMessage(), null, $exception);
        }

        try {
            // Attempt to validate the JWT

View on GitHub (pinned to 9d2f6fc0a0)