/** * @param \Psr\Http\Message\ServerRequestInterface $request * @param \OAuth2\Token\AuthCodeInterface $authCode * * @throws \OAuth2\Exception\BaseExceptionInterface */ protected function checkPKCE(ServerRequestInterface $request, AuthCodeInterface $authCode) { $params = $authCode->getQueryParams(); if (!array_key_exists('code_challenge', $params)) { return; } $code_verifier = RequestBody::getParameter($request, 'code_verifier'); if (null === $code_verifier) { throw $this->getExceptionManager()->getException(ExceptionManagerInterface::BAD_REQUEST, ExceptionManagerInterface::INVALID_REQUEST, 'The parameter "code_verifier" is required.'); } $code_challenge = $params['code_challenge']; $code_challenge_method = array_key_exists('code_challenge_method', $params) ? $params['code_challenge'] : 'plain'; if (!in_array($code_challenge_method, ['plain', 'S256'])) { throw $this->getExceptionManager()->getException(ExceptionManagerInterface::BAD_REQUEST, ExceptionManagerInterface::INVALID_REQUEST, 'Unsupported "code_challenge_method".'); } $calculated = 'plain' === $code_challenge_method ? $code_verifier : Base64Url::encode(hash('sha256', $code_verifier, true)); if (!hash_equals($code_challenge, $calculated)) { throw $this->getExceptionManager()->getException(ExceptionManagerInterface::BAD_REQUEST, ExceptionManagerInterface::INVALID_REQUEST, 'Invalid parameter "code_verifier".'); } }
/** * @param \Psr\Http\Message\ServerRequestInterface $request * @param \OAuth2\Token\AuthCodeInterface $authCode * @param \OAuth2\Client\ClientInterface $client * * @throws \OAuth2\Exception\BaseExceptionInterface */ private function checkPKCE(ServerRequestInterface $request, AuthCodeInterface $authCode, ClientInterface $client) { $params = $authCode->getQueryParams(); if (!array_key_exists('code_challenge', $params)) { if (true === $this->isPKCEForPublicClientsEnforced() && $client->isPublic()) { throw $this->getExceptionManager()->getBadRequestException(ExceptionManagerInterface::ERROR_INVALID_REQUEST, 'Non-confidential clients must set a proof key (PKCE) for code exchange.'); } return; } $code_challenge = $params['code_challenge']; $code_challenge_method = array_key_exists('code_challenge_method', $params) ? $params['code_challenge_method'] : 'plain'; $code_verifier = RequestBody::getParameter($request, 'code_verifier'); try { $this->getPKCEMethodManager()->checkPKCEInput($code_challenge_method, $code_challenge, $code_verifier); } catch (\InvalidArgumentException $e) { throw $this->getExceptionManager()->getBadRequestException(ExceptionManagerInterface::ERROR_INVALID_REQUEST, $e->getMessage()); } }