thephpleague/oauth2-server · error · OAuthServerException

Access token is not an instance of UnencryptedToken

Error message

Access token is not an instance of UnencryptedToken

What it means

Guard inside validateAuthorization(): the string parsed from the Authorization header is a JWE (encrypted token) or otherwise not an UnencryptedToken, so its claims (such as the jti used for revocation checks) cannot be read. This server issues/accepts only signed, unencrypted JWTs, so an encrypted or opaque token presented as a bearer credential is rejected.

Solutions

  1. Send the standard (unencrypted JWS) access token issued by league/oauth2-server.
  2. Ensure the issuer doesn't encrypt tokens (JWE); use signed-only JWTs.
  3. Confirm the client isn't sending an ID token or refresh token in the Authorization header.

Example fix

// before
$request = $request->withHeader('Authorization', 'Bearer ' . $idToken);
// after
$request = $request->withHeader('Authorization', 'Bearer ' . $accessToken);
Defensive patterns

Strategy: type-guard

Validate before calling

$jwt = substr($header, 7);
if (substr_count($jwt, '.') !== 2) throw new \RuntimeException('Not a JWS access token');

Type guard

function isUnencryptedJwt(string $token): bool { $p = explode('.', $token); return count($p) === 3 && $p[0] !== '' && $p[2] !== ''; }

Try / catch

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

Prevention

When it happens

Trigger: Client sends an encrypted token or a non-JWT opaque string that the parser accepted (e.g. a signed JWE, or a token type from a different library).

Common situations: Issuer uses JWE encryption while validator expects unencrypted JWS; client sends an ID token/session cookie instead of an access token.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at src/AuthorizationValidators/BearerTokenValidator.php:125

        }

        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
            $constraints = $this->jwtConfiguration->validationConstraints();
            $this->jwtConfiguration->validator()->assert($token, ...$constraints);
        } catch (RequiredConstraintsViolated $exception) {
            throw OAuthServerException::accessDenied('Access token could not be verified', null, $exception);
        }

        if (!$token instanceof UnencryptedToken) {
            throw OAuthServerException::accessDenied('Access token is not an instance of UnencryptedToken');
        }

        $claims = $token->claims();

        // Check if token has been revoked
        if ($this->accessTokenRepository->isAccessTokenRevoked($claims->get('jti'))) {
            throw OAuthServerException::accessDenied('Access token has been revoked');
        }

        // Return the request with additional attributes
        return $request
            ->withAttribute('oauth_access_token_id', $claims->get('jti'))
            ->withAttribute('oauth_client_id', $claims->get('aud')[0])
            ->withAttribute('oauth_user_id', $claims->get('sub'))
            ->withAttribute('oauth_scopes', $claims->get('scopes'));
    }
}

View on GitHub (pinned to 9d2f6fc0a0)