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 "code" parameter
What it means
Thrown by the authorization code grant's respondToAccessTokenRequest when the token request has no 'code' parameter to exchange. The grant validates the client, then reads the required 'code' request parameter; its absence makes the token exchange request invalid under the OAuth2 spec.
Solutions
- Ensure the token request includes the code parameter received from the authorization redirect: POST code=<authorization_code> with grant_type=authorization_code
- Verify your HTTP layer forwards the authorization response's ?code=... query value to the token request body
- Check parameter naming — it must be exactly 'code', not 'auth_code' or 'authorization_code'
- In tests, add 'code' to the request body before calling respondToAccessTokenRequest
Example fix
// before
const body = { grant_type: 'authorization_code', client_id, redirect_uri };
// after
const body = { grant_type: 'authorization_code', client_id, redirect_uri, code: authCode }; Defensive patterns
Strategy: validation
Validate before calling
if (!authCode || typeof authCode !== 'string') {
throw new Error('authorization code missing — cannot call token endpoint');
} Type guard
function hasAuthCode(q: Record<string, unknown>): q is Record<string, string> & { code: string } { return typeof q.code === 'string' && q.code.length > 0; } Try / catch
try {
return await tokenClient.exchange({ grant_type: 'authorization_code', code, ... });
} catch (e) {
if (e.code === 'invalid_request' && e.hint?.includes('code')) {
console.error('Token request missing code parameter');
}
throw e;
} Prevention
- Always carry the ?code query value from the authorization redirect into the token request body
- Use the exact parameter name 'code' in the token request
- Validate the token request payload in the client before sending
- Persist the code (session/storage) if the redirect and exchange happen in different requests
When it happens
Trigger: POSTing to /access_token with grant_type=authorization_code but omitting the code parameter, sending it under a different key (e.g. authorization_code or authCode), or the client losing the code between the redirect and the token call.
Common situations: Client-side redirect handlers store the code in state but never include it in the token request; frontend/backend mismatches where the frontend strips query params; single-page apps calling the token endpoint with only code_verifier and client_id; integration tests whose POST body lacks 'code'.
Understand the failure class
- 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/7144e1f22bcb9f70.
Report an issue: GitHub.
Appendix: source
Thrown at src/Grant/AuthCodeGrant.php:105
$this->requireCodeChallengeForPublicClients = false;
}
/**
* Respond to an access token request.
*
* @throws OAuthServerException
*/
public function respondToAccessTokenRequest(
ServerRequestInterface $request,
ResponseTypeInterface $responseType,
DateInterval $accessTokenTTL
): ResponseTypeInterface {
$client = $this->validateClient($request);
$encryptedAuthCode = $this->getRequestParameter('code', $request);
if ($encryptedAuthCode === null) {
throw OAuthServerException::invalidRequest('code');
}
try {
$authCodePayload = json_decode($this->decrypt($encryptedAuthCode));
$this->validateAuthorizationCode($authCodePayload, $client, $request);
$scopes = $this->scopeRepository->finalizeScopes(
$this->validateScopes($authCodePayload->scopes),
$this->getIdentifier(),
$client,
$authCodePayload->user_id,
$authCodePayload->auth_code_id
);
} catch (InvalidArgumentException $e) {
throw OAuthServerException::invalidGrant('Cannot validate the provided authorization code');
} catch (LogicException $e) {
throw OAuthServerException::invalidRequest('code', 'Issue decrypting the authorization code', $e);View on GitHub (pinned to 9d2f6fc0a0)