/**
  * {@inheritdoc}
  */
 public function respondToAccessTokenRequest(ServerRequestInterface $request, ResponseTypeInterface $responseType, \DateInterval $accessTokenTTL)
 {
     // Validate request
     $client = $this->validateClient($request);
     $scopes = $this->validateScopes($this->getRequestParameter('scope', $request));
     // Finalize the requested scopes
     $scopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client);
     // Issue and persist access token
     $accessToken = $this->issueAccessToken($accessTokenTTL, $client, null, $scopes);
     // Inject access token into response type
     $responseType->setAccessToken($accessToken);
     return $responseType;
 }
 /**
  * Get the token type that grants will return in the HTTP response.
  *
  * @return ResponseTypeInterface
  */
 protected function getResponseType()
 {
     if ($this->responseType instanceof ResponseTypeInterface === false) {
         $this->responseType = new BearerTokenResponse();
     }
     $this->responseType->setPrivateKey($this->privateKey);
     return $this->responseType;
 }
 /**
  * {@inheritdoc}
  */
 public function respondToAccessTokenRequest(ServerRequestInterface $request, ResponseTypeInterface $responseType, DateInterval $accessTokenTTL)
 {
     // Validate request
     $client = $this->validateClient($request);
     $scopes = $this->validateScopes($this->getRequestParameter('scope', $request));
     // Finalize the requested scopes
     $scopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client);
     $userIdentifier = $this->getRequestParameter('user_id', $request);
     if (is_null($userIdentifier)) {
         throw OAuthServerException::invalidRequest('user_id');
     }
     $this->tokenName = $this->getRequestParameter('token_name', $request);
     if (is_null($this->tokenName)) {
         throw OAuthServerException::invalidRequest('token_name');
     }
     // Issue and persist access token
     $accessToken = $this->issueAccessToken(new DateInterval('P5Y'), $client, $userIdentifier, $scopes);
     // Inject access token into response type
     $responseType->setAccessToken($accessToken);
     return $responseType;
 }
 /**
  * {@inheritdoc}
  */
 public function respondToAccessTokenRequest(ServerRequestInterface $request, ResponseTypeInterface $responseType, \DateInterval $accessTokenTTL)
 {
     // Validate request
     $client = $this->validateClient($request);
     $oldRefreshToken = $this->validateOldRefreshToken($request, $client->getIdentifier());
     $scopes = $this->validateScopes($this->getRequestParameter('scope', $request));
     // If no new scopes are requested then give the access token the original session scopes
     if (count($scopes) === 0) {
         $scopes = array_map(function ($scopeId) use($client) {
             $scope = $this->scopeRepository->getScopeEntityByIdentifier($scopeId);
             if ($scope instanceof ScopeEntityInterface === false) {
                 // @codeCoverageIgnoreStart
                 throw OAuthServerException::invalidScope($scopeId);
                 // @codeCoverageIgnoreEnd
             }
             return $scope;
         }, $oldRefreshToken['scopes']);
     } else {
         // The OAuth spec says that a refreshed access token can have the original scopes or fewer so ensure
         // the request doesn't include any new scopes
         foreach ($scopes as $scope) {
             if (in_array($scope->getIdentifier(), $oldRefreshToken['scopes']) === false) {
                 throw OAuthServerException::invalidScope($scope->getIdentifier());
             }
         }
     }
     // Expire old tokens
     $this->accessTokenRepository->revokeAccessToken($oldRefreshToken['access_token_id']);
     $this->refreshTokenRepository->revokeRefreshToken($oldRefreshToken['refresh_token_id']);
     // Issue and persist new tokens
     $accessToken = $this->issueAccessToken($accessTokenTTL, $client, $oldRefreshToken['user_id'], $scopes);
     $refreshToken = $this->issueRefreshToken($accessToken);
     // Inject tokens into response
     $responseType->setAccessToken($accessToken);
     $responseType->setRefreshToken($refreshToken);
     return $responseType;
 }
 /**
  * Respond to an access token request.
  *
  * @param \Psr\Http\Message\ServerRequestInterface                  $request
  * @param \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface $responseType
  * @param \DateInterval                                             $accessTokenTTL
  *
  * @throws \League\OAuth2\Server\Exception\OAuthServerException
  *
  * @return \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface
  */
 public function respondToAccessTokenRequest(ServerRequestInterface $request, ResponseTypeInterface $responseType, DateInterval $accessTokenTTL)
 {
     // Validate request
     $client = $this->validateClient($request);
     $encryptedAuthCode = $this->getRequestParameter('code', $request, null);
     if ($encryptedAuthCode === null) {
         throw OAuthServerException::invalidRequest('code');
     }
     // Validate the authorization code
     try {
         $authCodePayload = json_decode($this->decrypt($encryptedAuthCode));
         if (time() > $authCodePayload->expire_time) {
             throw OAuthServerException::invalidRequest('code', 'Authorization code has expired');
         }
         if ($this->authCodeRepository->isAuthCodeRevoked($authCodePayload->auth_code_id) === true) {
             throw OAuthServerException::invalidRequest('code', 'Authorization code has been revoked');
         }
         if ($authCodePayload->client_id !== $client->getIdentifier()) {
             throw OAuthServerException::invalidRequest('code', 'Authorization code was not issued to this client');
         }
         // The redirect URI is required in this request
         $redirectUri = $this->getRequestParameter('redirect_uri', $request, null);
         if (empty($authCodePayload->redirect_uri) === false && $redirectUri === null) {
             throw OAuthServerException::invalidRequest('redirect_uri');
         }
         if ($authCodePayload->redirect_uri !== $redirectUri) {
             throw OAuthServerException::invalidRequest('redirect_uri', 'Invalid redirect URI');
         }
         $scopes = [];
         foreach ($authCodePayload->scopes as $scopeId) {
             $scope = $this->scopeRepository->getScopeEntityByIdentifier($scopeId);
             if (!$scope instanceof ScopeEntityInterface) {
                 // @codeCoverageIgnoreStart
                 throw OAuthServerException::invalidScope($scopeId);
                 // @codeCoverageIgnoreEnd
             }
             $scopes[] = $scope;
         }
         // Finalize the requested scopes
         $scopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client, $authCodePayload->user_id);
     } catch (\LogicException $e) {
         throw OAuthServerException::invalidRequest('code', 'Cannot decrypt the authorization code');
     }
     // Validate code challenge
     if ($this->enableCodeExchangeProof === true) {
         $codeVerifier = $this->getRequestParameter('code_verifier', $request, null);
         if ($codeVerifier === null) {
             throw OAuthServerException::invalidRequest('code_verifier');
         }
         switch ($authCodePayload->code_challenge_method) {
             case 'plain':
                 if (hash_equals($codeVerifier, $authCodePayload->code_challenge) === false) {
                     throw OAuthServerException::invalidGrant('Failed to verify `code_verifier`.');
                 }
                 break;
             case 'S256':
                 if (hash_equals(urlencode(base64_encode(hash('sha256', $codeVerifier))), $authCodePayload->code_challenge) === false) {
                     throw OAuthServerException::invalidGrant('Failed to verify `code_verifier`.');
                 }
                 // @codeCoverageIgnoreStart
                 break;
             default:
                 throw OAuthServerException::serverError(sprintf('Unsupported code challenge method `%s`', $authCodePayload->code_challenge_method));
                 // @codeCoverageIgnoreEnd
         }
     }
     // Issue and persist access + refresh tokens
     $accessToken = $this->issueAccessToken($accessTokenTTL, $client, $authCodePayload->user_id, $scopes);
     $refreshToken = $this->issueRefreshToken($accessToken);
     // Inject tokens into response type
     $responseType->setAccessToken($accessToken);
     $responseType->setRefreshToken($refreshToken);
     // Revoke used auth code
     $this->authCodeRepository->revokeAuthCode($authCodePayload->auth_code_id);
     return $responseType;
 }