public function handleCallback(array $query) { $qState = isset($query['state']) ? $query['state'] : null; $qCode = isset($query['code']) ? $query['code'] : null; $qError = isset($query['error']) ? $query['error'] : null; $qErrorDescription = isset($query['error_description']) ? $query['error_description'] : null; if (null === $qState) { throw new CallbackException("state parameter missing"); } $state = $this->tokenStorage->getState($this->clientConfigId, $qState); if (false === $state) { throw new CallbackException("state not found"); } // avoid race condition for state by really needing a confirmation // that it was deleted if (false === $this->tokenStorage->deleteState($state)) { throw new CallbackException("state already used"); } if (null === $qCode && null === $qError) { throw new CallbackException("both code and error parameter missing"); } if (null !== $qError) { // FIXME: this should probably be CallbackException? throw new AuthorizeException($qError, $qErrorDescription); } if (null !== $qCode) { $t = new TokenRequest($this->httpClient, $this->clientConfig); $tokenResponse = $t->withAuthorizationCode($qCode); if (false === $tokenResponse) { throw new CallbackException("unable to fetch access token with authorization code"); } if (null === $tokenResponse->getScope()) { // no scope in response, we assume we got the requested scope $scope = $state->getScope(); } else { // the scope we got should be a superset of what we requested $scope = $tokenResponse->getScope(); if (!$scope->hasScope($state->getScope())) { // we didn't get the scope we requested, stop for now // FIXME: we need to implement a way to request certain // scope as being optional, while others need to be // required throw new CallbackException("requested scope not obtained"); } } // store the access token $accessToken = new AccessToken(array("client_config_id" => $this->clientConfigId, "user_id" => $state->getUserId(), "scope" => $scope, "access_token" => $tokenResponse->getAccessToken(), "token_type" => $tokenResponse->getTokenType(), "issue_time" => time(), "expires_in" => $tokenResponse->getExpiresIn())); $this->tokenStorage->storeAccessToken($accessToken); // if we also got a refresh token in the response, store that as // well if (null !== $tokenResponse->getRefreshToken()) { $refreshToken = new RefreshToken(array("client_config_id" => $this->clientConfigId, "user_id" => $state->getUserId(), "scope" => $scope, "refresh_token" => $tokenResponse->getRefreshToken(), "issue_time" => time())); $this->tokenStorage->storeRefreshToken($refreshToken); } return $accessToken; } }
public function getAccessToken(Context $context) { // do we have a valid access token? $accessToken = $this->tokenStorage->getAccessToken($this->clientConfigId, $context); if (false !== $accessToken) { if (null === $accessToken->getExpiresIn()) { // no expiry set, assume always valid return $accessToken; } // check if expired if (time() < $accessToken->getIssueTime() + $accessToken->getExpiresIn()) { // not expired return $accessToken; } // expired, delete it and continue $this->tokenStorage->deleteAccessToken($accessToken); } // no valid access token, is there a refresh_token? $refreshToken = $this->getRefreshToken($context); if (false !== $refreshToken) { // obtain a new access token with refresh token $tokenRequest = new TokenRequest($this->httpClient, $this->clientConfig); $tokenResponse = $tokenRequest->withRefreshToken($refreshToken->getRefreshToken()); if (false === $tokenResponse) { // unable to fetch with RefreshToken, delete it $this->tokenStorage->deleteRefreshToken($refreshToken); return false; } if (null === $tokenResponse->getScope()) { // no scope in response, we assume we got the requested scope $scope = $context->getScope(); } else { // the scope we got should be a superset of what we requested $scope = $tokenResponse->getScope(); if (!$scope->hasScope($context->getScope())) { // we didn't get the scope we requested, stop for now // FIXME: we need to implement a way to request certain // scope as being optional, while others need to be // required throw new ApiException("requested scope not obtained"); } } $accessToken = new AccessToken(array("client_config_id" => $this->clientConfigId, "user_id" => $context->getUserId(), "scope" => $scope, "access_token" => $tokenResponse->getAccessToken(), "token_type" => $tokenResponse->getTokenType(), "issue_time" => time(), "expires_in" => $tokenResponse->getExpiresIn())); $this->tokenStorage->storeAccessToken($accessToken); if (null !== $tokenResponse->getRefreshToken()) { // delete the existing refresh token as we'll store a new one $this->tokenStorage->deleteRefreshToken($refreshToken); $refreshToken = new RefreshToken(array("client_config_id" => $this->clientConfigId, "user_id" => $context->getUserId(), "scope" => $scope, "refresh_token" => $tokenResponse->getRefreshToken(), "issue_time" => time())); $this->tokenStorage->storeRefreshToken($refreshToken); } return $accessToken; } // no access token, and refresh token didn't work either or was not there, probably the tokens were revoked return false; }