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
- Append client_id to the authorization URL: /authorize?response_type=token&client_id=YOUR_ID&redirect_uri=...
- If using HTTP Basic auth, confirm the client actually sends the Authorization header (curl -u client_id:secret)
- Check your redirect/link generation and any proxy rewrite rules that may strip query strings
- 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
- Generate authorization links from a single template that always includes client_id
- Add an integration test asserting the /authorize URL contains client_id
- Check reverse-proxy rewrite rules do not strip query strings
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.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
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)