getQueryParams()['user_code']); } /** * @throws \League\OAuth2\Server\Exception\OAuthServerException */ public function validateAuthorizationRequest(ServerRequestInterface $request): AuthorizationRequestInterface { $userCode = $this->getQueryStringParameter('user_code', $request); if ($userCode === null) { throw OAuthServerException::invalidRequest('user_code'); } $deviceCode = $this->deviceCodeRepository->getDeviceCodeEntityByUserCode($userCode); if ($deviceCode === null) { throw new OAuthServerException('Unknown user code', 4, 'invalid_user_code', 401); } if ($deviceCode->getUserIdentifier() !== null) { throw new OAuthServerException('The user code has already been used', 6, 'used_user_code', 400); } $authorizationRequest = new AuthorizationRequest(); $authorizationRequest->setGrantTypeId($this->getIdentifier()); $authorizationRequest->setClient($deviceCode->getClient()); $authorizationRequest->setScopes($deviceCode->getScopes()); // We need the device code during the "completeAuthorizationRequest" implementation, so store it inside some unused field. // Perfectly the implementation must rely on the "user code" but library's implementation built on top of the "device code". $authorizationRequest->setCodeChallenge($deviceCode->getIdentifier()); return $authorizationRequest; } /** * @throws \League\OAuth2\Server\Exception\OAuthServerException */ public function completeAuthorizationRequest(AuthorizationRequestInterface $authorizationRequest): ResponseTypeInterface { $this->completeDeviceAuthorizationRequest( $authorizationRequest->getCodeChallenge(), $authorizationRequest->getUser()->getIdentifier(), $authorizationRequest->isAuthorizationApproved(), ); return new EmptyResponse(); } }