Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support a token store interface within the OAuth2 implementation #301

Closed
Scorcher opened this issue Aug 30, 2014 · 5 comments
Closed

Support a token store interface within the OAuth2 implementation #301

Scorcher opened this issue Aug 30, 2014 · 5 comments
Assignees
Labels
type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design.

Comments

@Scorcher
Copy link

Multi threaded or multi process apps can get race condition, when each process/thread will refresh token and store it to storage "simultaneously".
It would be great to have opportunity implement thread-safe TokenProvider and set it to Google_Client

Example:

interface ITokenProvider {
    public function getToken();
}

class MyTokenProvider implements ITokenProvider {
    public function getToken()
    {
        // TODO: Implement getToken() method from somewhere
    }
}

$client = new Google_Client();
$client->setTokenProvider(new MyTokenProvider());
@Scorcher
Copy link
Author

Now I wrote these code to have opportunity multiprocess communicate with API. TokenProvider is more pretty :) and can be integrated with onRefreshCallback idea #300.

// method called after each library (api) request
    protected function checkAndUpdateToken()
    {
        $newToken = $this->getClient()->getAccessToken();
        if ( $newToken !== $this->token )
        {
            $currentToken = GoogleTokens::updateTokenByAccount($this->clientId,
                $this->accountName, $newToken);
            $this->token = $currentToken;
            if ( $newToken !== $currentToken )
                $this->getClient()->setAccessToken($this->token);
        }
    }


    /**
     * Set Token to storage if it is newer then already stored and return current token
     *
     * @param string $clientId - clientId
     * @param string $accountName - account name
     * @param string $token - new token
     *
     * @return string current token
     *
     * @throws CException
     */
    public static function updateTokenByAccount($clientId, $accountName, $token)
    {
        if ( self::getLock() === false )
            throw new CException('Can not get lock to update token');
        // get token from storage
        $criteria = new CDbCriteria;
        $criteria->compare( 'client_id', $clientId, false );
        $criteria->compare( 'account_name', $accountName, false );
        /** @var GoogleTokens $googleToken */
        $googleToken = self::model()->find($criteria);
        if ( $googleToken === null )
        {
            // set base data if it is new
            $googleToken = new self();
            $googleToken->client_id = $clientId;
            $googleToken->account_name = $accountName;
        }
        else
        {
            // compare age of stored and new token
            $tStored = json_decode($googleToken->token);
            $tNew = json_decode($token);
            if ( $tNew['created'] < $tStored['created'] )
            {
                // if stored token is newer - just return it without saving "new one"
                self::releaseLock();
                return $googleToken->token;
            }
        }
        $googleToken->lastUpdate = date('Y-m-d H:i:s');
        $googleToken->token = $token;
        if ( $googleToken->save() !== true )
            throw new CException('Can not save token by account: clientId='.$clientId
            .'; accountName='.$accountName.';');
        self::releaseLock();

        return $token;
    }

@ianbarber ianbarber changed the title Oauth2: ITokenProvider Support a token store interface within the OAuth2 implementation Sep 8, 2014
@ianbarber
Copy link
Contributor

Agree that having a pluggable token store would be a nice general feature - for more than just multithread usage, but automatically having some sort of default store for refresh tokens and so on with some persistence.

@ianbarber ianbarber added the type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design. label Sep 8, 2014
@tmatsuo
Copy link

tmatsuo commented Jan 9, 2017

@Scorcher Is this issue still relevant? If so, are you able to create a pull request for this feature?

@tmatsuo tmatsuo self-assigned this Jan 9, 2017
@tmatsuo
Copy link

tmatsuo commented Feb 8, 2017

@bshaffer I think the implementation around token has been changed, so can we close this now?

@bshaffer
Copy link
Contributor

bshaffer commented Feb 9, 2017

Closing this. Google_Client has a setTokenCallback method that can be used to handle this situation. Also, the Cache class can be customized by anything implementing the PSR-6 standard.

@bshaffer bshaffer closed this as completed Feb 9, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design.
Projects
None yet
Development

No branches or pull requests

4 participants