{"record":{"id":"4f24e008ba7270da","repo":"thephpleague/oauth2-server","slug":"invalid-request-4f24e0","errorCode":"invalid_request","errorMessage":"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 \"username\" parameter","messagePattern":"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 \"username\" parameter","errorType":"http","errorClass":"OAuthServerException","httpStatus":400,"severity":"error","filePath":"src/Grant/PasswordGrant.php","lineNumber":86,"sourceCode":"\n        // Issue and persist new refresh token if given\n        $refreshToken = $this->issueRefreshToken($accessToken);\n\n        if ($refreshToken !== null) {\n            $this->getEmitter()->emit(new RequestRefreshTokenEvent(RequestEvent::REFRESH_TOKEN_ISSUED, $request, $refreshToken));\n            $responseType->setRefreshToken($refreshToken);\n        }\n\n        return $responseType;\n    }\n\n    /**\n     * @throws OAuthServerException\n     */\n    protected function validateUser(ServerRequestInterface $request, ClientEntityInterface $client): UserEntityInterface\n    {\n        $username = $this->getRequestParameter('username', $request)\n            ?? throw OAuthServerException::invalidRequest('username');\n\n        $password = $this->getRequestParameter('password', $request)\n            ?? throw OAuthServerException::invalidRequest('password');\n\n        $user = $this->userRepository->getUserEntityByUserCredentials(\n            $username,\n            $password,\n            $this->getIdentifier(),\n            $client\n        );\n\n        if ($user instanceof UserEntityInterface === false) {\n            $this->getEmitter()->emit(new RequestEvent(RequestEvent::USER_AUTHENTICATION_FAILED, $request));\n\n            throw OAuthServerException::invalidCredentials();\n        }\n\n        return $user;","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/thephpleague/oauth2-server/blob/9d2f6fc0a0b5aa1bb02506971d3a4ecff2c6526c/src/Grant/PasswordGrant.php#L68-L104","documentation":"PasswordGrant::validateUser throws invalidRequest('username') when the token request body has no 'username' parameter. The password grant mandates both username and password in the POST body (application/x-www-form-urlencoded). The generic invalid_request message names the offending parameter to help the caller fix the request.","triggerScenarios":"POST to the token endpoint with grant_type=password but no username field; getRequestParameter('username', $request) returns null so the ?? throw triggers; validateUser is invoked from respondToAccessTokenRequest.","commonSituations":"Client sends JSON body while the server only parses form-encoded parameters; parameter name typo (user_name, email); frontend forgets to include username in the token request; middleware strips or rewrites the request body.","solutions":["Send the token request as form-encoded with a username field: POST grant_type=password&username=...&password=...","If your client sends JSON, switch to form data or configure the server to parse JSON bodies before calling the grant","Check for typos in parameter names on the client side","Log the parsed body server-side to confirm what the grant actually receives"],"exampleFix":"// before\nawait fetch('/token', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({grant_type:'password', username, password}) });\n// after\nawait fetch('/token', { method: 'POST', headers: {'Content-Type': 'application/x-www-form-urlencoded'}, body: new URLSearchParams({grant_type:'password', username, password}) });","handlingStrategy":"validation","validationCode":"$params = (array) $request->getParsedBody();\nif (!isset($params['username']) || !is_string($params['username']) || $params['username'] === '') {\n    throw new \\InvalidArgumentException('username required');\n}","typeGuard":"function hasUsername(array $params): bool {\n    return isset($params['username']) && is_string($params['username']) && $params['username'] !== '';\n}","tryCatchPattern":"try {\n    $token = $server->respondToAccessTokenRequest($request, $response);\n} catch (OAuthServerException $e) {\n    if (str_contains($e->getMessage(), '\"username\"')) {\n        return $e->generateHttpResponse($response->withStatus(400));\n    }\n    throw $e;\n}","preventionTips":["Send token requests as application/x-www-form-urlencoded","Assert required fields client-side before hitting the token endpoint","Never send JSON bodies unless the server is configured to parse them"],"tags":["oauth2","password-grant","missing-parameter","php"],"backgroundTag":"missing-required-argument","analyzedSha":"9d2f6fc0a0b5aa1bb02506971d3a4ecff2c6526c","analyzedAt":"2026-09-15T22:33:30.452Z","contentChangedAt":"2026-09-15T22:33:30.452Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}