rpicms

A CMS for the Raspberry Pi
git clone git://archive.git.mtrnord.blog/RpicmsTeam/rpicms.git
Log | Files | Refs | README | LICENSE

Callback.php (6117B)


      1 <?php
      2 
      3 /**
      4  *  This program is free software: you can redistribute it and/or modify
      5  *  it under the terms of the GNU Lesser General Public License as published by
      6  *  the Free Software Foundation, either version 3 of the License, or
      7  *  (at your option) any later version.
      8  *
      9  *  This program is distributed in the hope that it will be useful,
     10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12  *  GNU Lesser General Public License for more details.
     13  *
     14  *  You should have received a copy of the GNU Lesser General Public License
     15  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
     16  */
     17 
     18 namespace fkooman\OAuth\Client;
     19 
     20 use fkooman\OAuth\Client\Exception\CallbackException;
     21 
     22 // FIXME: replace AuthorizeException with CallbackException?
     23 use fkooman\OAuth\Client\Exception\AuthorizeException;
     24 use Guzzle\Http\Client;
     25 
     26 class Callback
     27 {
     28     private $clientConfigId;
     29     private $clientConfig;
     30     private $tokenStorage;
     31     private $httpClient;
     32 
     33     public function __construct(
     34         $clientConfigId,
     35         ClientConfigInterface $clientConfig,
     36         StorageInterface $tokenStorage,
     37         Client $httpClient
     38     ) {
     39         $this->setClientConfigId($clientConfigId);
     40         $this->setClientConfig($clientConfig);
     41         $this->setTokenStorage($tokenStorage);
     42         $this->setHttpClient($httpClient);
     43     }
     44 
     45     public function setClientConfigId($clientConfigId)
     46     {
     47         if (!is_string($clientConfigId) || 0 >= strlen($clientConfigId)) {
     48             throw new CallbackException("clientConfigId should be a non-empty string");
     49         }
     50         $this->clientConfigId = $clientConfigId;
     51     }
     52 
     53     public function getClientConfigId()
     54     {
     55         return $this->clientConfigId;
     56     }
     57 
     58     public function setClientConfig(ClientConfigInterface $clientConfig)
     59     {
     60         $this->clientConfig = $clientConfig;
     61     }
     62 
     63     public function getClientConfig()
     64     {
     65         return $this->clientConfig;
     66     }
     67 
     68     public function setTokenStorage(StorageInterface $tokenStorage)
     69     {
     70         $this->tokenStorage = $tokenStorage;
     71     }
     72 
     73     public function getTokenStorage()
     74     {
     75         return $this->tokenStorage;
     76     }
     77 
     78     public function setHttpClient(Client $httpClient)
     79     {
     80         $this->httpClient = $httpClient;
     81     }
     82 
     83     public function getHttpClient()
     84     {
     85         return $this->httpClient;
     86     }
     87 
     88     public function handleCallback(array $query)
     89     {
     90         $queryState = isset($query['state']) ? $query['state'] : null;
     91         $queryCode = isset($query['code']) ? $query['code'] : null;
     92         $queryError = isset($query['error']) ? $query['error'] : null;
     93         $queryErrorDescription = isset($query['error_description']) ? $query['error_description'] : null;
     94 
     95         if (null === $queryState) {
     96             throw new CallbackException("state parameter missing");
     97         }
     98         $state = $this->tokenStorage->getState($this->clientConfigId, $queryState);
     99         if (false === $state) {
    100             throw new CallbackException("state not found");
    101         }
    102 
    103         // avoid race condition for state by really needing a confirmation
    104         // that it was deleted
    105         if (false === $this->tokenStorage->deleteState($state)) {
    106             throw new CallbackException("state already used");
    107         }
    108 
    109         if (null === $queryCode && null === $queryError) {
    110             throw new CallbackException("both code and error parameter missing");
    111         }
    112 
    113         if (null !== $queryError) {
    114             // FIXME: this should probably be CallbackException?
    115             throw new AuthorizeException($queryError, $queryErrorDescription);
    116         }
    117 
    118         if (null !== $queryCode) {
    119             $t = new TokenRequest($this->httpClient, $this->clientConfig);
    120             $tokenResponse = $t->withAuthorizationCode($queryCode);
    121             if (false === $tokenResponse) {
    122                 throw new CallbackException("unable to fetch access token with authorization code");
    123             }
    124 
    125             if (null === $tokenResponse->getScope()) {
    126                 // no scope in response, we assume we got the initially requested scope
    127                 $scope = $state->getScope();
    128             } else {
    129                 // the scope we got should be a superset of what we requested
    130                 $scope = $tokenResponse->getScope();
    131                 if (!$scope->hasScope($state->getScope())) {
    132                     // we didn't get the scope we requested, stop for now
    133                     // FIXME: we need to implement a way to request certain
    134                     // scope as being optional, while others need to be
    135                     // required
    136                     throw new CallbackException("requested scope not obtained");
    137                 }
    138             }
    139 
    140             // store the access token
    141             $accessToken = new AccessToken(
    142                 array(
    143                     "client_config_id" => $this->clientConfigId,
    144                     "user_id" => $state->getUserId(),
    145                     "scope" => $scope,
    146                     "access_token" => $tokenResponse->getAccessToken(),
    147                     "token_type" => $tokenResponse->getTokenType(),
    148                     "issue_time" => time(),
    149                     "expires_in" => $tokenResponse->getExpiresIn(),
    150                 )
    151             );
    152             $this->tokenStorage->storeAccessToken($accessToken);
    153 
    154             // if we also got a refresh token in the response, store that as
    155             // well
    156             if (null !== $tokenResponse->getRefreshToken()) {
    157                 $refreshToken = new RefreshToken(
    158                     array(
    159                         "client_config_id" => $this->clientConfigId,
    160                         "user_id" => $state->getUserId(),
    161                         "scope" => $scope,
    162                         "refresh_token" => $tokenResponse->getRefreshToken(),
    163                         "issue_time" => time(),
    164                     )
    165                 );
    166                 $this->tokenStorage->storeRefreshToken($refreshToken);
    167             }
    168 
    169             return $accessToken;
    170         }
    171     }
    172 }