Complex classes like BasePassportServer often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use BasePassportServer, and based on these observations, apply Extract Interface, too.
| 1 | <?php namespace Limoncello\Passport; |
||
| 46 | abstract class BasePassportServer extends BaseAuthorizationServer implements PassportServerInterface, LAI |
||
| 47 | { |
||
| 48 | use LoggerAwareTrait; |
||
| 49 | |||
| 50 | /** |
||
| 51 | * @param PassportServerIntegrationInterface $integration |
||
| 52 | * @param ServerRequestInterface $request |
||
| 53 | * @param array $parameters |
||
| 54 | * @param string $realm |
||
| 55 | * |
||
| 56 | * @return ClientInterface|null |
||
| 57 | * |
||
| 58 | * @SuppressWarnings(PHPMD.NPathComplexity) |
||
| 59 | * @SuppressWarnings(PHPMD.CyclomaticComplexity) |
||
| 60 | */ |
||
| 61 | abstract protected function determineClient( |
||
| 67 | |||
| 68 | /** |
||
| 69 | * @var PassportServerIntegrationInterface |
||
| 70 | */ |
||
| 71 | private $integration; |
||
| 72 | |||
| 73 | /** |
||
| 74 | * @param PassportServerIntegrationInterface $integration |
||
| 75 | */ |
||
| 76 | 17 | public function __construct(PassportServerIntegrationInterface $integration) |
|
| 82 | |||
| 83 | /** |
||
| 84 | * @inheritdoc |
||
| 85 | * |
||
| 86 | * @SuppressWarnings(PHPMD.CyclomaticComplexity) |
||
| 87 | */ |
||
| 88 | 9 | protected function createAuthorization(array $parameters): ResponseInterface |
|
| 124 | |||
| 125 | /** |
||
| 126 | * @inheritdoc |
||
| 127 | */ |
||
| 128 | 8 | public function postCreateToken(ServerRequestInterface $request): ResponseInterface |
|
| 129 | { |
||
| 130 | try { |
||
| 131 | 8 | $parameters = $request->getParsedBody(); |
|
| 132 | 8 | $determinedClient = $this->determineClient($this->getIntegration(), $request, $parameters); |
|
|
|
|||
| 133 | |||
| 134 | 8 | switch ($grantType = $this->getGrantType($parameters)) { |
|
| 135 | 8 | case GrantTypes::AUTHORIZATION_CODE: |
|
| 136 | 1 | $this->logDebug('Handling code grant.'); |
|
| 137 | 1 | $response = $this->codeIssueToken($parameters, $determinedClient); |
|
| 138 | 1 | break; |
|
| 139 | 7 | case GrantTypes::RESOURCE_OWNER_PASSWORD_CREDENTIALS: |
|
| 140 | 4 | $this->logDebug('Handling resource owner password grant.'); |
|
| 141 | 4 | $response = $this->passIssueToken($parameters, $determinedClient); |
|
| 142 | 3 | break; |
|
| 143 | 5 | case GrantTypes::CLIENT_CREDENTIALS: |
|
| 144 | 2 | $this->logDebug('Handling client credentials grant.'); |
|
| 145 | 2 | if ($determinedClient === null) { |
|
| 146 | 1 | $this->logInfo('Client identification failed.'); |
|
| 147 | 1 | throw new OAuthTokenBodyException(OAuthTokenBodyException::ERROR_INVALID_CLIENT); |
|
| 148 | } |
||
| 149 | 1 | $response = $this->clientIssueToken($parameters, $determinedClient); |
|
| 150 | 1 | break; |
|
| 151 | 3 | case GrantTypes::REFRESH_TOKEN: |
|
| 152 | 2 | $this->logDebug('Handling refresh token grant.'); |
|
| 153 | 2 | $response = $this->refreshIssueToken($parameters, $determinedClient); |
|
| 154 | 2 | break; |
|
| 155 | default: |
||
| 156 | 1 | $this->logInfo('Unknown grant type.', ['grant_type' => $grantType]); |
|
| 157 | 6 | throw new OAuthTokenBodyException(OAuthTokenBodyException::ERROR_UNSUPPORTED_GRANT_TYPE); |
|
| 158 | } |
||
| 159 | 4 | } catch (OAuthTokenBodyException $exception) { |
|
| 160 | 4 | $response = $this->createBodyErrorResponse($exception); |
|
| 161 | } |
||
| 162 | |||
| 163 | 8 | return $response; |
|
| 164 | } |
||
| 165 | |||
| 166 | /** |
||
| 167 | * @inheritdoc |
||
| 168 | */ |
||
| 169 | 2 | public function createCodeResponse(TokenInterface $code, string $state = null): ResponseInterface |
|
| 170 | { |
||
| 171 | 2 | $client = $this->readClientByIdentifier($code->getClientIdentifier()); |
|
| 172 | 2 | if ($code->getRedirectUriString() === null || |
|
| 173 | 2 | in_array($code->getRedirectUriString(), $client->getRedirectUriStrings()) === false |
|
| 174 | ) { |
||
| 175 | 1 | $this->logInfo( |
|
| 176 | 1 | 'Code has invalid redirect URI which do not match any redirect URI for its client.', |
|
| 177 | 1 | ['id' => $code->getIdentifier()] |
|
| 178 | ); |
||
| 179 | 1 | return $this->getIntegration()->createInvalidClientAndRedirectUriErrorResponse(); |
|
| 180 | } |
||
| 181 | |||
| 182 | 1 | $code->setCode($this->getIntegration()->generateCodeValue($code)); |
|
| 183 | |||
| 184 | 1 | $tokenRepo = $this->getIntegration()->getTokenRepository(); |
|
| 185 | 1 | $createdCode = $tokenRepo->createCode($code); |
|
| 186 | |||
| 187 | 1 | $response = $this->createRedirectCodeResponse($createdCode, $state); |
|
| 188 | |||
| 189 | 1 | return $response; |
|
| 190 | } |
||
| 191 | |||
| 192 | /** |
||
| 193 | * @inheritdoc |
||
| 194 | */ |
||
| 195 | 2 | public function createTokenResponse(TokenInterface $token, string $state = null): ResponseInterface |
|
| 196 | { |
||
| 197 | 2 | $client = $this->readClientByIdentifier($token->getClientIdentifier()); |
|
| 198 | 2 | if ($token->getRedirectUriString() === null || |
|
| 199 | 2 | in_array($token->getRedirectUriString(), $client->getRedirectUriStrings()) === false |
|
| 200 | ) { |
||
| 201 | 1 | $this->logInfo( |
|
| 202 | 1 | 'Token has invalid redirect URI which do not match any redirect URI for its client.', |
|
| 203 | 1 | ['id' => $token->getIdentifier()] |
|
| 204 | ); |
||
| 205 | 1 | return $this->getIntegration()->createInvalidClientAndRedirectUriErrorResponse(); |
|
| 206 | } |
||
| 207 | |||
| 208 | 1 | list($tokenValue, $tokenType, $tokenExpiresIn) = $this->getIntegration()->generateTokenValues($token); |
|
| 209 | |||
| 210 | // refresh value must be null by the spec |
||
| 211 | 1 | $refreshValue = null; |
|
| 212 | 1 | $token->setValue($tokenValue)->setType($tokenType)->setRefreshValue($refreshValue); |
|
| 213 | 1 | $savedToken = $this->getIntegration()->getTokenRepository()->createToken($token); |
|
| 214 | |||
| 215 | 1 | $response = $this->createRedirectTokenResponse($savedToken, $tokenExpiresIn, $state); |
|
| 216 | |||
| 217 | 1 | return $response; |
|
| 218 | } |
||
| 219 | |||
| 220 | /** @noinspection PhpTooManyParametersInspection |
||
| 221 | * @inheritdoc |
||
| 222 | * |
||
| 223 | * @SuppressWarnings(PHPMD.BooleanArgumentFlag) |
||
| 224 | */ |
||
| 225 | 3 | public function codeCreateAskResourceOwnerForApprovalResponse( |
|
| 226 | ClientInterface $client, |
||
| 227 | string $redirectUri = null, |
||
| 228 | bool $isScopeModified = false, |
||
| 229 | array $scopeList = null, |
||
| 230 | string $state = null, |
||
| 231 | array $extraParameters = [] |
||
| 232 | ): ResponseInterface { |
||
| 233 | 3 | $this->logDebug('Asking resource owner for scope approval (code grant).'); |
|
| 234 | 3 | return $this->getIntegration()->createAskResourceOwnerForApprovalResponse( |
|
| 235 | 3 | ResponseTypes::AUTHORIZATION_CODE, |
|
| 236 | 3 | $client, |
|
| 237 | 3 | $redirectUri, |
|
| 238 | 3 | $isScopeModified, |
|
| 239 | 3 | $scopeList, |
|
| 240 | 3 | $state, |
|
| 241 | 3 | $extraParameters |
|
| 242 | ); |
||
| 243 | } |
||
| 244 | |||
| 245 | /** |
||
| 246 | * @inheritdoc |
||
| 247 | */ |
||
| 248 | 1 | public function codeReadAuthenticationCode(string $code): ?AuthorizationCodeInterface |
|
| 249 | { |
||
| 250 | 1 | return $this->getIntegration()->getTokenRepository() |
|
| 251 | 1 | ->readByCode($code, $this->getIntegration()->getCodeExpirationPeriod()); |
|
| 252 | } |
||
| 253 | |||
| 254 | /** |
||
| 255 | * @inheritdoc |
||
| 256 | */ |
||
| 257 | 1 | public function codeCreateAccessTokenResponse( |
|
| 258 | AuthorizationCodeInterface $code, |
||
| 259 | array $extraParameters = [] |
||
| 260 | ): ResponseInterface { |
||
| 261 | /** @var Token $code */ |
||
| 262 | 1 | assert($code instanceof Token); |
|
| 263 | 1 | $updatedToken = clone $code; |
|
| 264 | |||
| 265 | 1 | $tokenExpiresIn = $this->setUpTokenValues($updatedToken); |
|
| 266 | 1 | $this->getIntegration()->getTokenRepository()->assignValuesToCode($updatedToken, $tokenExpiresIn); |
|
| 267 | |||
| 268 | 1 | $response = $this->createBodyTokenResponse($updatedToken, $tokenExpiresIn); |
|
| 269 | |||
| 270 | 1 | $this->logInfo('Authorization code successfully exchanged for a token (code grant).'); |
|
| 271 | |||
| 272 | 1 | return $response; |
|
| 273 | } |
||
| 274 | |||
| 275 | /** |
||
| 276 | * @inheritdoc |
||
| 277 | */ |
||
| 278 | 1 | public function codeRevokeTokens(AuthorizationCodeInterface $code): void |
|
| 279 | { |
||
| 280 | 1 | assert($code instanceof TokenInterface); |
|
| 281 | |||
| 282 | /** @var TokenInterface $code */ |
||
| 283 | |||
| 284 | 1 | $identifier = $code->getIdentifier(); |
|
| 285 | 1 | $this->logInfo('Revoking token.', ['token_id' => $identifier]); |
|
| 286 | 1 | $this->getIntegration()->getTokenRepository()->disable($identifier); |
|
| 287 | } |
||
| 288 | |||
| 289 | /** @noinspection PhpTooManyParametersInspection |
||
| 290 | * @inheritdoc |
||
| 291 | * |
||
| 292 | * @SuppressWarnings(PHPMD.BooleanArgumentFlag) |
||
| 293 | */ |
||
| 294 | 2 | public function implicitCreateAskResourceOwnerForApprovalResponse( |
|
| 295 | ClientInterface $client, |
||
| 296 | string $redirectUri = null, |
||
| 297 | bool $isScopeModified = false, |
||
| 298 | array $scopeList = null, |
||
| 299 | string $state = null, |
||
| 300 | array $extraParameters = [] |
||
| 301 | ): ResponseInterface { |
||
| 302 | 2 | $response = $this->getIntegration()->createAskResourceOwnerForApprovalResponse( |
|
| 303 | 2 | ResponseTypes::IMPLICIT, |
|
| 304 | 2 | $client, |
|
| 305 | 2 | $redirectUri, |
|
| 306 | 2 | $isScopeModified, |
|
| 307 | 2 | $scopeList, |
|
| 308 | 2 | $state, |
|
| 309 | 2 | $extraParameters |
|
| 310 | ); |
||
| 311 | |||
| 312 | 2 | $this->logInfo('Created response asking resource owner for scope approval (implicit grant).'); |
|
| 313 | |||
| 314 | 2 | return $response; |
|
| 315 | } |
||
| 316 | |||
| 317 | /** @noinspection PhpTooManyParametersInspection |
||
| 318 | * @inheritdoc |
||
| 319 | * |
||
| 320 | * @SuppressWarnings(PHPMD.BooleanArgumentFlag) |
||
| 321 | */ |
||
| 322 | 4 | public function passValidateCredentialsAndCreateAccessTokenResponse( |
|
| 323 | string $userName, |
||
| 324 | string $password, |
||
| 325 | ClientInterface $client = null, |
||
| 326 | bool $isScopeModified = false, |
||
| 327 | array $scope = null, |
||
| 328 | array $extraParameters = [] |
||
| 329 | ): ResponseInterface { |
||
| 330 | 4 | assert($client !== null); |
|
| 331 | |||
| 332 | 4 | if (($userIdentifier = $this->getIntegration()->validateUserId($userName, $password)) === null) { |
|
| 333 | 1 | $this->logDebug('User not found with provided username and password.', ['username' => $userName]); |
|
| 334 | 1 | throw new OAuthTokenBodyException(OAuthTokenBodyException::ERROR_INVALID_GRANT); |
|
| 335 | } |
||
| 336 | 3 | assert(is_int($userIdentifier) === true); |
|
| 337 | 3 | $this->logInfo('User authenticated with provided username and password.', ['username' => $userName]); |
|
| 338 | |||
| 339 | 3 | $changedScopeOrNull = $this->getIntegration()->verifyAllowedUserScope($userIdentifier, $scope); |
|
| 340 | 3 | if ($changedScopeOrNull !== null) { |
|
| 341 | 3 | assert(is_array($changedScopeOrNull)); |
|
| 342 | 3 | $isScopeModified = true; |
|
| 343 | 3 | $scope = $changedScopeOrNull; |
|
| 344 | } |
||
| 345 | |||
| 346 | 3 | $unsavedToken = $this->getIntegration()->createTokenInstance(); |
|
| 347 | $unsavedToken |
||
| 348 | 3 | ->setClientIdentifier($client->getIdentifier()) |
|
| 349 | 3 | ->setScopeIdentifiers($scope) |
|
| 350 | 3 | ->setUserIdentifier($userIdentifier); |
|
| 351 | 3 | $isScopeModified === true ? $unsavedToken->setScopeModified() : $unsavedToken->setScopeUnmodified(); |
|
| 352 | |||
| 353 | |||
| 354 | 3 | $tokenExpiresIn = $this->setUpTokenValues($unsavedToken); |
|
| 355 | 3 | $savedToken = $this->getIntegration()->getTokenRepository()->createToken($unsavedToken); |
|
| 356 | |||
| 357 | 3 | $response = $this->createBodyTokenResponse($savedToken, $tokenExpiresIn); |
|
| 358 | |||
| 359 | 3 | return $response; |
|
| 360 | } |
||
| 361 | |||
| 362 | /** |
||
| 363 | * @inheritdoc |
||
| 364 | */ |
||
| 365 | 4 | public function passReadDefaultClient(): ClientInterface |
|
| 366 | { |
||
| 367 | 4 | $defaultClientId = $this->getIntegration()->getDefaultClientIdentifier(); |
|
| 368 | |||
| 369 | 4 | assert(is_string($defaultClientId) === true && empty($defaultClientId) === false); |
|
| 370 | |||
| 371 | 4 | $defaultClient = $this->readClientByIdentifier($defaultClientId); |
|
| 372 | |||
| 373 | 4 | assert($defaultClient !== null); |
|
| 374 | |||
| 375 | 4 | return $defaultClient; |
|
| 376 | } |
||
| 377 | |||
| 378 | /** |
||
| 379 | * @inheritdoc |
||
| 380 | */ |
||
| 381 | 1 | public function clientCreateAccessTokenResponse( |
|
| 382 | ClientInterface $client, |
||
| 383 | bool $isScopeModified, |
||
| 384 | array $scope = null, |
||
| 385 | array $extraParameters = [] |
||
| 386 | ): ResponseInterface { |
||
| 387 | 1 | $this->logDebug('Prepare token for client.'); |
|
| 388 | 1 | assert($client !== null); |
|
| 389 | |||
| 390 | 1 | $unsavedToken = $this->getIntegration()->createTokenInstance(); |
|
| 391 | $unsavedToken |
||
| 392 | 1 | ->setClientIdentifier($client->getIdentifier()) |
|
| 393 | 1 | ->setScopeIdentifiers($scope); |
|
| 394 | 1 | $isScopeModified === true ? $unsavedToken->setScopeModified() : $unsavedToken->setScopeUnmodified(); |
|
| 395 | |||
| 396 | |||
| 397 | 1 | $tokenExpiresIn = $this->setUpTokenValue($unsavedToken); |
|
| 398 | 1 | $savedToken = $this->getIntegration()->getTokenRepository()->createToken($unsavedToken); |
|
| 399 | |||
| 400 | 1 | $response = $this->createBodyTokenResponse($savedToken, $tokenExpiresIn); |
|
| 401 | |||
| 402 | 1 | return $response; |
|
| 403 | } |
||
| 404 | |||
| 405 | /** |
||
| 406 | * @inheritdoc |
||
| 407 | * |
||
| 408 | * @return TokenInterface|null |
||
| 409 | */ |
||
| 410 | 2 | public function readTokenByRefreshValue(string $refreshValue): ?\Limoncello\OAuthServer\Contracts\TokenInterface |
|
| 411 | { |
||
| 412 | 2 | return $this->getIntegration()->getTokenRepository()->readByRefresh( |
|
| 413 | 2 | $refreshValue, |
|
| 414 | 2 | $this->getIntegration()->getTokenExpirationPeriod() |
|
| 415 | ); |
||
| 416 | } |
||
| 417 | |||
| 418 | /** |
||
| 419 | * @inheritdoc |
||
| 420 | * |
||
| 421 | * @SuppressWarnings(PHPMD.ElseExpression) |
||
| 422 | */ |
||
| 423 | 2 | public function refreshCreateAccessTokenResponse( |
|
| 424 | ClientInterface $client, |
||
| 425 | \Limoncello\OAuthServer\Contracts\TokenInterface $token, |
||
| 426 | bool $isScopeModified, |
||
| 427 | array $scope = null, |
||
| 428 | array $extraParameters = [] |
||
| 429 | ): ResponseInterface { |
||
| 430 | 2 | $this->logDebug('Prepare refresh token.'); |
|
| 431 | |||
| 432 | /** @var TokenInterface $token */ |
||
| 433 | 2 | assert($token instanceof TokenInterface); |
|
| 434 | |||
| 435 | 2 | $updatedToken = clone $token; |
|
| 436 | 2 | $tokenExpiresIn = $this->getIntegration()->isRenewRefreshValue() === false ? |
|
| 437 | 2 | $this->setUpTokenValue($updatedToken) : $this->setUpTokenValues($updatedToken); |
|
| 438 | |||
| 439 | 2 | $tokenRepo = $this->getIntegration()->getTokenRepository(); |
|
| 440 | 2 | if ($isScopeModified === false) { |
|
| 441 | 1 | $tokenRepo->updateValues($updatedToken); |
|
| 442 | } else { |
||
| 443 | 1 | assert(is_array($scope)); |
|
| 444 | 1 | $tokenRepo->inTransaction(function () use ($tokenRepo, $updatedToken, $scope) { |
|
| 445 | 1 | $tokenRepo->updateValues($updatedToken); |
|
| 446 | 1 | $tokenRepo->unbindScopes($updatedToken->getIdentifier()); |
|
| 447 | 1 | $tokenRepo->bindScopeIdentifiers($updatedToken->getIdentifier(), $scope); |
|
| 448 | 1 | }); |
|
| 449 | 1 | $updatedToken->setScopeModified()->setScopeIdentifiers($scope); |
|
| 450 | } |
||
| 451 | 2 | $response = $this->createBodyTokenResponse($updatedToken, $tokenExpiresIn); |
|
| 452 | |||
| 453 | 2 | return $response; |
|
| 454 | } |
||
| 455 | |||
| 456 | /** |
||
| 457 | * @inheritdoc |
||
| 458 | */ |
||
| 459 | 13 | public function readClientByIdentifier(string $clientIdentifier): ?ClientInterface |
|
| 460 | { |
||
| 461 | 13 | return $this->getIntegration()->getClientRepository()->read($clientIdentifier); |
|
| 462 | } |
||
| 463 | |||
| 464 | /** |
||
| 465 | * @param string|null $clientId |
||
| 466 | * @param string|null $redirectFromQuery |
||
| 467 | * |
||
| 468 | * @return array [client|null, uri|null] |
||
| 469 | * |
||
| 470 | * @SuppressWarnings(PHPMD.ElseExpression) |
||
| 471 | */ |
||
| 472 | 9 | protected function getValidClientAndRedirectUri(string $clientId = null, string $redirectFromQuery = null): array |
|
| 473 | { |
||
| 474 | 9 | $client = null; |
|
| 475 | 9 | $validRedirectUri = null; |
|
| 476 | |||
| 477 | 9 | if ($clientId !== null && |
|
| 478 | 9 | ($client = $this->readClientByIdentifier($clientId)) !== null |
|
| 479 | ) { |
||
| 480 | 7 | $validRedirectUri = $this->selectValidRedirectUri($client, $redirectFromQuery); |
|
| 481 | 7 | if ($validRedirectUri === null) { |
|
| 482 | 1 | $this->logDebug( |
|
| 483 | 1 | 'Choosing valid redirect URI for client failed.', |
|
| 484 | 7 | ['client_id' => $clientId, 'redirect_uri_from_query' => $redirectFromQuery] |
|
| 485 | ); |
||
| 486 | } |
||
| 487 | } else { |
||
| 488 | 2 | $this->logDebug('Client is not found.', ['client_id' => $clientId]); |
|
| 489 | } |
||
| 490 | |||
| 491 | 9 | return [$client, $validRedirectUri]; |
|
| 492 | } |
||
| 493 | |||
| 494 | /** |
||
| 495 | * @param TokenInterface $token |
||
| 496 | * @param int $tokenExpiresIn |
||
| 497 | * |
||
| 498 | * @return ResponseInterface |
||
| 499 | */ |
||
| 500 | 5 | protected function createBodyTokenResponse(TokenInterface $token, int $tokenExpiresIn): ResponseInterface |
|
| 501 | { |
||
| 502 | 5 | $this->logDebug('Sending token as JSON response.'); |
|
| 503 | |||
| 504 | 5 | $scopeList = $token->isScopeModified() === false || empty($token->getScopeIdentifiers()) === true ? |
|
| 505 | 5 | null : $token->getScopeList(); |
|
| 506 | |||
| 507 | // for access token format @link https://tools.ietf.org/html/rfc6749#section-5.1 |
||
| 508 | 5 | $parameters = $this->filterNulls([ |
|
| 509 | 5 | 'access_token' => $token->getValue(), |
|
| 510 | 5 | 'token_type' => $token->getType(), |
|
| 511 | 5 | 'expires_in' => $tokenExpiresIn, |
|
| 512 | 5 | 'refresh_token' => $token->getRefreshValue(), |
|
| 513 | 5 | 'scope' => $scopeList, |
|
| 514 | ]); |
||
| 515 | |||
| 516 | // extra parameters |
||
| 517 | // https://tools.ietf.org/html/rfc6749#section-4.1.4 |
||
| 518 | // https://tools.ietf.org/html/rfc6749#section-4.3.3 |
||
| 519 | // https://tools.ietf.org/html/rfc6749#section-4.4.3 |
||
| 520 | 5 | $extraParameters = $this->getIntegration()->getBodyTokenExtraParameters($token); |
|
| 521 | |||
| 522 | 5 | $response = new JsonResponse($parameters + $extraParameters, 200, [ |
|
| 523 | 5 | 'Cache-Control' => 'no-store', |
|
| 524 | 'Pragma' => 'no-cache' |
||
| 525 | ]); |
||
| 526 | |||
| 527 | 5 | return $response; |
|
| 528 | } |
||
| 529 | |||
| 530 | /** |
||
| 531 | * @param TokenInterface $code |
||
| 532 | * @param string|null $state |
||
| 533 | * |
||
| 534 | * @return ResponseInterface |
||
| 535 | */ |
||
| 536 | 1 | protected function createRedirectCodeResponse(TokenInterface $code, string $state = null): ResponseInterface |
|
| 537 | { |
||
| 538 | 1 | $this->logDebug('Sending code as redirect response.'); |
|
| 539 | |||
| 540 | // for access token format @link https://tools.ietf.org/html/rfc6749#section-4.1.3 |
||
| 541 | 1 | $parameters = $this->filterNulls([ |
|
| 542 | 1 | 'code' => $code->getCode(), |
|
| 543 | 1 | 'state' => $state, |
|
| 544 | ]); |
||
| 545 | |||
| 546 | 1 | $redirectUri = $code->getRedirectUriString(); |
|
| 547 | 1 | $query = $this->encodeAsXWwwFormUrlencoded($parameters); |
|
| 548 | |||
| 549 | 1 | $response = new RedirectResponse((new Uri($redirectUri))->withQuery($query)); |
|
| 550 | |||
| 551 | 1 | return $response; |
|
| 552 | } |
||
| 553 | |||
| 554 | /** |
||
| 555 | * @param TokenInterface $token |
||
| 556 | * @param int $tokenExpiresIn |
||
| 557 | * @param string|null $state |
||
| 558 | * |
||
| 559 | * @return ResponseInterface |
||
| 560 | */ |
||
| 561 | 1 | protected function createRedirectTokenResponse( |
|
| 562 | TokenInterface $token, |
||
| 563 | int $tokenExpiresIn, |
||
| 564 | string $state = null |
||
| 565 | ): ResponseInterface { |
||
| 566 | 1 | $this->logDebug('Sending token as redirect response.'); |
|
| 567 | |||
| 568 | 1 | $scopeList = $token->isScopeModified() === false || empty($token->getScopeIdentifiers()) === true ? |
|
| 569 | 1 | null : $token->getScopeList(); |
|
| 570 | |||
| 571 | // for access token format @link https://tools.ietf.org/html/rfc6749#section-5.1 |
||
| 572 | 1 | $parameters = $this->filterNulls([ |
|
| 573 | 1 | 'access_token' => $token->getValue(), |
|
| 574 | 1 | 'token_type' => $token->getType(), |
|
| 575 | 1 | 'expires_in' => $tokenExpiresIn, |
|
| 576 | 1 | 'scope' => $scopeList, |
|
| 577 | 1 | 'state' => $state, |
|
| 578 | ]); |
||
| 579 | |||
| 580 | 1 | $fragment = $this->encodeAsXWwwFormUrlencoded($parameters); |
|
| 581 | |||
| 582 | 1 | $response = new RedirectResponse((new Uri($token->getRedirectUriString()))->withFragment($fragment)); |
|
| 583 | |||
| 584 | 1 | return $response; |
|
| 585 | } |
||
| 586 | |||
| 587 | /** |
||
| 588 | * @param OAuthTokenBodyException $exception |
||
| 589 | * |
||
| 590 | * @return ResponseInterface |
||
| 591 | */ |
||
| 592 | 4 | protected function createBodyErrorResponse(OAuthTokenBodyException $exception): ResponseInterface |
|
| 593 | { |
||
| 594 | 4 | $data = $this->filterNulls([ |
|
| 595 | 4 | 'error' => $exception->getErrorCode(), |
|
| 596 | 4 | 'error_description' => $exception->getErrorDescription(), |
|
| 597 | 4 | 'error_uri' => $this->getBodyErrorUri($exception), |
|
| 598 | ]); |
||
| 599 | |||
| 600 | 4 | $this->logDebug('Sending OAuth error as JSON response.', $data); |
|
| 601 | |||
| 602 | 4 | $response = new JsonResponse($data, $exception->getHttpCode(), $exception->getHttpHeaders()); |
|
| 603 | |||
| 604 | 4 | return $response; |
|
| 605 | } |
||
| 606 | |||
| 607 | /** |
||
| 608 | * @param OAuthRedirectException $exception |
||
| 609 | * |
||
| 610 | * @return ResponseInterface |
||
| 611 | */ |
||
| 612 | 1 | protected function createRedirectErrorResponse(OAuthRedirectException $exception): ResponseInterface |
|
| 613 | { |
||
| 614 | 1 | $parameters = $this->filterNulls([ |
|
| 615 | 1 | 'error' => $exception->getErrorCode(), |
|
| 616 | 1 | 'error_description' => $exception->getErrorDescription(), |
|
| 617 | 1 | 'error_uri' => $exception->getErrorUri(), |
|
| 618 | 1 | 'state' => $exception->getState(), |
|
| 619 | ]); |
||
| 620 | |||
| 621 | 1 | $this->logDebug('Sending OAuth error via redirect.', $parameters); |
|
| 622 | |||
| 623 | 1 | $fragment = $this->encodeAsXWwwFormUrlencoded($parameters); |
|
| 624 | 1 | $uri = (new Uri($exception->getRedirectUri()))->withFragment($fragment); |
|
| 625 | |||
| 626 | 1 | $response = new RedirectResponse($uri, 302, $exception->getHttpHeaders()); |
|
| 627 | |||
| 628 | 1 | return $response; |
|
| 629 | } |
||
| 630 | |||
| 631 | /** |
||
| 632 | * @param TokenInterface $token |
||
| 633 | * |
||
| 634 | * @return int |
||
| 635 | */ |
||
| 636 | 1 | protected function setUpTokenValue(TokenInterface $token): int |
|
| 637 | { |
||
| 638 | list($tokenValue, $tokenType, $tokenExpiresIn) = |
||
| 639 | 1 | $this->getIntegration()->generateTokenValues($token); |
|
| 640 | 1 | $token->setValue($tokenValue)->setType($tokenType); |
|
| 641 | |||
| 642 | 1 | return $tokenExpiresIn; |
|
| 643 | } |
||
| 644 | |||
| 645 | /** |
||
| 646 | * @param TokenInterface $token |
||
| 647 | * |
||
| 648 | * @return int |
||
| 649 | */ |
||
| 650 | 4 | protected function setUpTokenValues(TokenInterface $token): int |
|
| 651 | { |
||
| 652 | list($tokenValue, $tokenType, $tokenExpiresIn, $refreshValue) = |
||
| 653 | 4 | $this->getIntegration()->generateTokenValues($token); |
|
| 654 | 4 | $token->setValue($tokenValue)->setType($tokenType)->setRefreshValue($refreshValue); |
|
| 655 | |||
| 656 | 4 | return $tokenExpiresIn; |
|
| 657 | } |
||
| 658 | |||
| 659 | /** |
||
| 660 | * @return PassportServerIntegrationInterface |
||
| 661 | */ |
||
| 662 | 16 | protected function getIntegration(): PassportServerIntegrationInterface |
|
| 666 | |||
| 667 | /** |
||
| 668 | * @param PassportServerIntegrationInterface $integration |
||
| 669 | * |
||
| 670 | * @return self |
||
| 671 | */ |
||
| 672 | 17 | protected function setIntegration(PassportServerIntegrationInterface $integration): self |
|
| 673 | { |
||
| 674 | 17 | $this->integration = $integration; |
|
| 675 | |||
| 676 | 17 | return $this; |
|
| 677 | } |
||
| 678 | |||
| 679 | /** |
||
| 680 | * @param OAuthTokenBodyException $exception |
||
| 681 | * |
||
| 682 | * @return null|string |
||
| 683 | */ |
||
| 684 | 4 | protected function getBodyErrorUri(OAuthTokenBodyException $exception) |
|
| 685 | { |
||
| 686 | 4 | assert($exception !== null); |
|
| 687 | |||
| 688 | 4 | return null; |
|
| 689 | } |
||
| 690 | |||
| 691 | /** |
||
| 692 | * @param string $message |
||
| 693 | * @param array $context |
||
| 694 | * |
||
| 695 | * @return void |
||
| 696 | */ |
||
| 697 | 16 | protected function logDebug(string $message, array $context = []): void |
|
| 703 | |||
| 704 | /** |
||
| 705 | * @param string $message |
||
| 706 | * @param array $context |
||
| 707 | * |
||
| 708 | * @return void |
||
| 709 | */ |
||
| 710 | 10 | protected function logInfo(string $message, array $context = []): void |
|
| 716 | |||
| 717 | /** |
||
| 718 | * @param array $array |
||
| 719 | * |
||
| 720 | * @return array |
||
| 721 | */ |
||
| 722 | private function filterNulls(array $array): array |
||
| 728 | } |
||
| 729 |
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.