/**
  * {@inheritdoc}
  */
 public function validateAuthorization(\Phalcon\Http\RequestInterface $request)
 {
     if (!$request->getHeader('authorization')) {
         throw OAuthServerException::accessDenied('Missing "Authorization" header');
     }
     $header = $request->getHeader('authorization');
     $jwt = trim(preg_replace('/^(?:\\s+)?Bearer\\s/', '', $header));
     try {
         // Attempt to parse and validate the JWT
         $token = (new Parser())->parse($jwt);
         if ($token->verify(new Sha256(), $this->publicKey->getKeyPath()) === false) {
             throw OAuthServerException::accessDenied('Access token could not be verified');
         }
         // Ensure access token hasn't expired
         $data = new ValidationData();
         $data->setCurrentTime(time());
         if ($token->validate($data) === false) {
             throw OAuthServerException::accessDenied('Access token is invalid');
         }
         // Check if token has been revoked
         if ($this->accessTokenRepository->isAccessTokenRevoked($token->getClaim('jti'))) {
             throw OAuthServerException::accessDenied('Access token has been revoked');
         }
         // Return the response with additional attributes
         $response = ['oauth_access_token_id' => $token->getClaim('jti'), 'oauth_client_id' => $token->getClaim('aud'), 'oauth_user_id' => $token->getClaim('sub'), 'oauth_scopes' => $token->getClaim('scopes')];
         return $response;
     } catch (\InvalidArgumentException $exception) {
         // JWT couldn't be parsed so return the request as is
         throw OAuthServerException::accessDenied($exception->getMessage());
     }
 }
 /**
  * check if client have right scopes to access the route.
  *
  * @param $neededScopes
  * @param $requestedScopes
  *
  * @throws OAuthServerException
  *
  * @return bool
  */
 protected function validateScopes($neededScopes, $requestedScopes)
 {
     if (empty($neededScopes)) {
         return true;
     }
     foreach ($requestedScopes as $requestedScope) {
         if (in_array($requestedScope->getIdentifier(), $neededScopes)) {
             return true;
         }
     }
     throw OAuthServerException::accessDenied('you need right scope to access this resource');
 }
 /**
  * @param \Psr\Http\Message\ServerRequestInterface             $request
  * @param \League\OAuth2\Server\Entities\ClientEntityInterface $client
  *
  * @throws \League\OAuth2\Server\Exception\OAuthServerException
  *
  * @return \League\OAuth2\Server\Entities\UserEntityInterface
  */
 protected function validateUser(ServerRequestInterface $request, ClientEntityInterface $client)
 {
     $username = $this->getRequestParameter('username', $request);
     if (is_null($username)) {
         throw OAuthServerException::invalidRequest('username');
     }
     $password = $this->getRequestParameter('password', $request);
     if (is_null($password)) {
         throw OAuthServerException::invalidRequest('password');
     }
     $user = $this->userRepository->getUserEntityByUserCredentials($username, $password, $this->getIdentifier(), $client);
     if (!$user instanceof UserEntityInterface) {
         $this->getEmitter()->emit(new RequestEvent(RequestEvent::USER_AUTHENTICATION_FAILED, $request));
         throw OAuthServerException::invalidCredentials();
     }
     return $user;
 }
Exemple #4
0
 /**
  * @param \lcon\Http\RequestInterface $request
  * @param \League\OAuth2\Server\Entities\ClientEntityInterface $client
  *
  * @throws \League\OAuth2\Server\Exception\OAuthServerException
  *
  * @return \League\OAuth2\Server\Entities\UserEntityInterface
  **/
 protected function validateUser(\Phalcon\Http\RequestInterface $request, ClientEntityInterface $client)
 {
     $username = $this->getRequestParameter('username', $request);
     if (is_null($username)) {
         throw OAuthServerException::invalidRequest('username', '`%s` parameter is missing');
     }
     $password = $this->getRequestParameter('password', $request);
     if (is_null($password)) {
         throw OAuthServerException::invalidRequest('password', '`%s` parameter is missing');
     }
     $user = $this->userRepository->getUserEntityByUserCredentials($username, $password, $this->getIdentifier(), $client);
     if (!$user instanceof UserEntityInterface) {
         $this->getEmitter()->emit(new RequestEvent('user.authentication.failed', $request));
         throw OAuthServerException::invalidCredentials();
     }
     return $user;
 }
 /**
  * {@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;
 }
Exemple #6
0
 public function getUserEntityByUserCredentials($username, $password, $grantType, ClientEntityInterface $clientEntity)
 {
     $builder = (new Builder())->columns(['User.id', 'User.username', 'User.password'])->addFrom(\Ivyhjk\OAuth2\Server\Adapter\Phalcon\Model\User::class, 'User')->where('User.username = :username:'******'username'))->limit(1);
     if ($this->getConfig()->limit_users_to_clients === true) {
         $builder->innerJoin(\Ivyhjk\OAuth2\Server\Adapter\Phalcon\Model\UserClient::class, 'UserClient.user_id = User.id', 'UserClient')->innerJoin(\Ivyhjk\OAuth2\Server\Adapter\Phalcon\Model\Client::class, 'Client.id = UserClient.client_id', 'Client')->andWhere('Client.id = :client_id:', ['client_id' => $clientEntity->getIdentifier()]);
     }
     if ($this->getConfig()->limit_users_to_grants === true) {
         $builder->innerJoin(\Ivyhjk\OAuth2\Server\Adapter\Phalcon\Model\UserGrant::class, 'UserGrant.user_id = User.id', 'UserGrant')->innerJoin(\Ivyhjk\OAuth2\Server\Adapter\Phalcon\Model\Grant::class, 'Grant.id = UserGrant.grant_id', 'Grant')->andWhere('Grant.id = :grantType:', compact('grantType'));
     }
     $query = $builder->getQuery();
     $result = $query->getSingleResult();
     if (!$result) {
         throw OAuthServerException::invalidCredentials();
     }
     $security = new Security();
     if ($security->checkHash($password, $result->password) !== true) {
         throw OAuthServerException::invalidCredentials();
     }
     $user = new UserEntity();
     $user->setIdentifier($result->id);
     return $user;
 }
Exemple #7
0
 /**
  * Get a client.
  *
  * @param string $clientIdentifier The client's identifier
  * @param string $grantType The grant type used
  * @param string $clientSecret The client's secret (if sent)
  *
  * @return \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface
  **/
 public function getClientEntity($clientIdentifier, $grantType, $clientSecret = null, $mustValidateSecret = true)
 {
     $builder = (new Builder())->columns(['Client.id', 'Client.secret', 'Client.name'])->addFrom(\Ivyhjk\OAuth2\Server\Adapter\Phalcon\Model\Client::class, 'Client')->where('Client.id = :clientIdentifier:', compact('clientIdentifier'))->limit(1);
     if ($mustValidateSecret === true) {
         $builder->andWhere('Client.secret = :clientSecret:', compact('clientSecret'));
     }
     //
     if ($this->getConfig()->limit_clients_to_grants === true) {
         $builder->innerJoin(\Ivyhjk\OAuth2\Server\Adapter\Phalcon\Model\ClientGrant::class, 'ClientGrant.client_id = Client.id', 'ClientGrant')->innerJoin(\Ivyhjk\OAuth2\Server\Adapter\Phalcon\Model\Grant::class, 'Grant.id = ClientGrant.grant_id', 'Grant')->andWhere('Grant.id = :grantType:', compact('grantType'));
     }
     $query = $builder->getQuery();
     $result = $query->getSingleResult();
     if (!$result) {
         throw OAuthServerException::invalidClient();
     }
     // Get one endpoint?
     // $builder = $this->getDatabase()->createBuilder();
     //
     // $builder
     //     ->columns([
     //         'ClientEndpoint.redirect_uri'
     //     ])
     //     ->addFrom(\Ivyhjk\OAuth2\Server\Adapter\Phalcon\Model\ClientEndpoint::class, 'ClientEndpoint')
     //     ->where('ClientEndpoint.client_id = :client_id:', [
     //         'client_id' => $result->id
     //     ])
     //     ->limit(1);
     //
     // $endpoint = $builder->getQuery()->getSingleResult();
     $client = new ClientEntity();
     $client->setName($result->name);
     $client->setIdentifier($result->id);
     // if ($endpoint) {
     //     $client->setRedirectUri($endpoint->redirect_uri);
     // }
     return $client;
 }
 /**
  * {@inheritdoc}
  */
 public function validateAuthorization(ServerRequestInterface $request)
 {
     if ($request->hasHeader('authorization') === false) {
         throw OAuthServerException::accessDenied('Missing "Authorization" header');
     }
     $header = $request->getHeader('authorization');
     $accessTokenId = trim($header[0]);
     try {
         $accessTokenEntity = $this->accessTokenRepository->findAccessToken($accessTokenId);
         // Check if token has been revoked
         if (is_null($accessTokenEntity)) {
             throw OAuthServerException::accessDenied('Access token has been revoked');
         }
         // Ensure access token hasn't expired
         if ($accessTokenEntity->getExpiryDateTime()->lt(Carbon::now())) {
             throw OAuthServerException::accessDenied('Access token is invalid');
         }
         // Return the request with additional attributes
         return $request->withAttribute('oauth_access_token_id', $accessTokenEntity->getIdentifier())->withAttribute('oauth_client_id', $accessTokenEntity->getClient()->getIdentifier())->withAttribute('oauth_user_id', $accessTokenEntity->getUserIdentifier())->withAttribute('oauth_scopes', $accessTokenEntity->getScopes());
     } catch (\InvalidArgumentException $exception) {
         // JWT couldn't be parsed so return the request as is
         throw OAuthServerException::accessDenied($exception->getMessage());
     }
 }
 /**
  * Return an access token response.
  *
  * @param ServerRequestInterface $request
  * @param ResponseInterface      $response
  *
  * @throws OAuthServerException
  *
  * @return ResponseInterface
  */
 public function respondToAccessTokenRequest(ServerRequestInterface $request, ResponseInterface $response)
 {
     foreach ($this->enabledGrantTypes as $grantType) {
         if ($grantType->canRespondToAccessTokenRequest($request)) {
             $tokenResponse = $grantType->respondToAccessTokenRequest($request, $this->getResponseType(), $this->grantTypeAccessTokenTTL[$grantType->getIdentifier()]);
             if ($tokenResponse instanceof ResponseTypeInterface) {
                 return $tokenResponse->generateHttpResponse($response);
             }
         }
     }
     throw OAuthServerException::unsupportedGrantType();
 }
Exemple #10
0
 /**
  * Generate a new unique identifier.
  *
  * @param int $length
  *
  * @throws \League\OAuth2\Server\Exception\OAuthServerException
  *
  * @return string
  */
 protected function generateUniqueIdentifier($length = 40)
 {
     try {
         return bin2hex(random_bytes($length));
         // @codeCoverageIgnoreStart
     } catch (\TypeError $e) {
         throw OAuthServerException::serverError('An unexpected error has occurred');
     } catch (\Error $e) {
         throw OAuthServerException::serverError('An unexpected error has occurred');
     } catch (\Exception $e) {
         // If you get this message, the CSPRNG failed hard.
         throw OAuthServerException::serverError('Could not generate a random string');
     }
     // @codeCoverageIgnoreEnd
 }
 /**
  * @param ServerRequestInterface $request
  * @param string                 $clientId
  *
  * @throws OAuthServerException
  *
  * @return array
  */
 protected function validateOldRefreshToken(ServerRequestInterface $request, $clientId)
 {
     $encryptedRefreshToken = $this->getRequestParameter('refresh_token', $request);
     if (is_null($encryptedRefreshToken)) {
         throw OAuthServerException::invalidRequest('refresh_token');
     }
     // Validate refresh token
     try {
         $refreshToken = $this->decrypt($encryptedRefreshToken);
     } catch (\LogicException $e) {
         throw OAuthServerException::invalidRefreshToken('Cannot decrypt the refresh token');
     }
     $refreshTokenData = json_decode($refreshToken, true);
     if ($refreshTokenData['client_id'] !== $clientId) {
         $this->getEmitter()->emit(new RequestEvent(RequestEvent::REFRESH_TOKEN_CLIENT_FAILED, $request));
         throw OAuthServerException::invalidRefreshToken('Token is not linked to client');
     }
     if ($refreshTokenData['expire_time'] < time()) {
         throw OAuthServerException::invalidRefreshToken('Token has expired');
     }
     if ($this->refreshTokenRepository->isRefreshTokenRevoked($refreshTokenData['refresh_token_id']) === true) {
         throw OAuthServerException::invalidRefreshToken('Token has been revoked');
     }
     return $refreshTokenData;
 }
 /**
  * {@inheritdoc}
  */
 public function completeAuthorizationRequest(AuthorizationRequest $authorizationRequest)
 {
     if ($authorizationRequest->getUser() instanceof UserEntityInterface === false) {
         throw new \LogicException('An instance of UserEntityInterface should be set on the AuthorizationRequest');
     }
     $finalRedirectUri = $authorizationRequest->getRedirectUri() === null ? is_array($authorizationRequest->getClient()->getRedirectUri()) ? $authorizationRequest->getClient()->getRedirectUri()[0] : $authorizationRequest->getClient()->getRedirectUri() : $authorizationRequest->getRedirectUri();
     // The user approved the client, redirect them back with an auth code
     if ($authorizationRequest->isAuthorizationApproved() === true) {
         $authCode = $this->issueAuthCode($this->authCodeTTL, $authorizationRequest->getClient(), $authorizationRequest->getUser()->getIdentifier(), $authorizationRequest->getRedirectUri(), $authorizationRequest->getScopes());
         $response = new RedirectResponse();
         $response->setRedirectUri($this->makeRedirectUri($finalRedirectUri, ['code' => $this->encrypt(json_encode(['client_id' => $authCode->getClient()->getIdentifier(), 'redirect_uri' => $authCode->getRedirectUri(), 'auth_code_id' => $authCode->getIdentifier(), 'scopes' => $authCode->getScopes(), 'user_id' => $authCode->getUserIdentifier(), 'expire_time' => (new \DateTime())->add($this->authCodeTTL)->format('U'), 'code_challenge' => $authorizationRequest->getCodeChallenge(), 'code_challenge_method  ' => $authorizationRequest->getCodeChallengeMethod()])), 'state' => $authorizationRequest->getState()]));
         return $response;
     }
     // The user denied the client, redirect them back with an error
     throw OAuthServerException::accessDenied('The user denied the request', $this->makeRedirectUri($finalRedirectUri, ['state' => $authorizationRequest->getState()]));
 }
 /**
  * Return an access token response.
  *
  * @param \Phalcon\Http\RequestInterface $request
  * @param \Ivyhjk\OAuth2\Server\Contract\Http\Response $response
  *
  * @throws \League\OAuth2\Server\Exception\OAuthServerException
  *
  * @return \Ivyhjk\OAuth2\Server\Contract\Http\Response
  **/
 public function respondToAccessTokenRequest(RequestContract $request, ResponseContract $response)
 {
     $tokenResponse = null;
     while ($tokenResponse === null && ($grantType = array_shift($this->enabledGrantTypes))) {
         /** @var \League\OAuth2\Server\Grant\GrantTypeInterface $grantType */
         if ($grantType->canRespondToAccessTokenRequest($request)) {
             $tokenResponse = $grantType->respondToAccessTokenRequest($request, $this->getResponseType(), $this->grantTypeAccessTokenTTL[$grantType->getIdentifier()]);
         }
     }
     if ($tokenResponse instanceof ResponseTypeContract) {
         return $tokenResponse->generateHttpResponse($response);
     }
     throw OAuthServerException::unsupportedGrantType();
 }
 public function __construct($resource, $identifier)
 {
     $message = sprintf(ERROR_MESSAGE, $resource, $identifier);
     $resource = strtolower(str_replace(' ', '_', $resource));
     parent::__construct($message, 100, sprintf('%s_not_found', $resource), 404);
 }
Exemple #15
0
 /**
  * {@inheritdoc}
  */
 public function completeAuthorizationRequest(AuthorizationRequest $authorizationRequest)
 {
     if ($authorizationRequest->getUser() instanceof UserEntityInterface === false) {
         throw new \LogicException('An instance of UserEntityInterface should be set on the AuthorizationRequest');
     }
     $finalRedirectUri = $authorizationRequest->getRedirectUri() === null ? is_array($authorizationRequest->getClient()->getRedirectUri()) ? $authorizationRequest->getClient()->getRedirectUri()[0] : $authorizationRequest->getClient()->getRedirectUri() : $authorizationRequest->getRedirectUri();
     // The user approved the client, redirect them back with an access token
     if ($authorizationRequest->isAuthorizationApproved() === true) {
         $accessToken = $this->issueAccessToken($this->accessTokenTTL, $authorizationRequest->getClient(), $authorizationRequest->getUser()->getIdentifier(), $authorizationRequest->getScopes());
         $response = new RedirectResponse();
         $response->setRedirectUri($this->makeRedirectUri($finalRedirectUri, ['access_token' => (string) $accessToken->convertToJWT($this->privateKey), 'token_type' => 'bearer', 'expires_in' => $accessToken->getExpiryDateTime()->getTimestamp() - (new \DateTime())->getTimestamp(), 'state' => $authorizationRequest->getState()], '#'));
         return $response;
     }
     // The user denied the client, redirect them back with an error
     throw OAuthServerException::accessDenied('The user denied the request', $this->makeRedirectUri($finalRedirectUri, ['state' => $authorizationRequest->getState()]));
 }