thephpleague/oauth2-server · error · OAuthServerException

invalid_request

invalid_request

Error message

The request is missing a required parameter, is invalid, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. Check the "client_id" parameter

What it means

ImplicitGrant::validateAuthorizationRequest throws invalid_request for the 'client_id' parameter when no client id can be resolved from the query string or HTTP Basic auth (PHP_AUTH_USER). Per RFC 6749 the authorization endpoint requires client_id, so an authorization request without one cannot proceed.

Solutions

  1. Append client_id to the authorization URL: /authorize?response_type=token&client_id=YOUR_ID&redirect_uri=...
  2. If using HTTP Basic auth, confirm the client actually sends the Authorization header (curl -u client_id:secret)
  3. Check your redirect/link generation and any proxy rewrite rules that may strip query strings
  4. Validate the outgoing authorization request in tests before shipping

Example fix

// before
header('Location: /authorize?response_type=token&redirect_uri=' . $uri);
// after
header('Location: /authorize?response_type=token&client_id=' . urlencode($clientId) . '&redirect_uri=' . urlencode($uri));
Defensive patterns

Strategy: validation

Validate before calling

const authUrl = new URL('/authorize', baseUrl);
if (!authUrl.searchParams.get('client_id')) {
    throw new Error('client_id must be present in the authorization URL');
}

Type guard

function hasClientId(ServerRequestInterface $r): bool {
    return $r->getQueryParams()['client_id'] !== null
        || $r->getServerParams()['PHP_AUTH_USER'] !== null;
}

Try / catch

try {
    $authRequest = $server->validateAuthorizationRequest($request);
} catch (OAuthServerException $e) {
    if (str_contains($e->getMessage(), 'client_id')) {
        return redirect('/login?error=missing_client_id');
    }
    throw $e;
}

Prevention

When it happens

Trigger: GET to the authorization endpoint via validateAuthorizationRequest with neither ?client_id= in the query string nor PHP_AUTH_USER set in the request; getServerParameter/getQueryStringParameter return null and OAuthServerException::invalidRequest('client_id') is thrown.

Common situations: Frontend redirects users to /authorize but drops the client_id query parameter; template/URL-building bug; reverse proxy strips query params; developer relies on HTTP Basic auth that the browser/client never sends.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at src/Grant/ImplicitGrant.php:103

        return (
            $request->getQueryParams()['response_type'] === 'token'
            && isset($request->getQueryParams()['client_id'])
        );
    }

    /**
     * {@inheritdoc}
     */
    public function validateAuthorizationRequest(ServerRequestInterface $request): AuthorizationRequestInterface
    {
        $clientId = $this->getQueryStringParameter(
            'client_id',
            $request,
            $this->getServerParameter('PHP_AUTH_USER', $request)
        );

        if (is_null($clientId)) {
            throw OAuthServerException::invalidRequest('client_id');
        }

        $client = $this->getClientEntityOrFail($clientId, $request);

        $redirectUri = $this->getQueryStringParameter('redirect_uri', $request);

        if ($redirectUri !== null) {
            $this->validateRedirectUri($redirectUri, $client, $request);
        } elseif (
            $client->getRedirectUri() === '' ||
            (is_array($client->getRedirectUri()) && count($client->getRedirectUri()) !== 1)
        ) {
            $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
            throw OAuthServerException::invalidClient($request);
        }

        $stateParameter = $this->getQueryStringParameter('state', $request);

View on GitHub (pinned to 9d2f6fc0a0)