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

Using refresh token grant type for 2-legged OAuth #14

Open
bogdanghervan opened this issue Jan 16, 2019 · 4 comments
Open

Using refresh token grant type for 2-legged OAuth #14

bogdanghervan opened this issue Jan 16, 2019 · 4 comments

Comments

@bogdanghervan
Copy link

We are trying to make the middleware work with a 2-legged OAuth flow. The server we are connecting to has already authorized our app, and we've been issued a refresh token (which doesn't seem to expire) that we can use to get new access tokens.

However, there's probably something I'm missing or the middleware is not quite designed for this.

I've made it work in the end, but perhaps there's a better way?

Here's my code:

$config = [
    'client_id' => 'ABC',
    'client_secret' => 'DEF',
    'refresh_token' => 'GHI'
];

$clientCredentialsGrantType = new ClientCredentials($refreshClient, $config);
$refreshTokenGrantType = new RefreshToken($refreshClient, $config);
            
$oauth = new OAuth2Middleware($clientCredentialsGrantType, $refreshTokenGrantType);
$oauth->setAccessToken([
    'refresh_token' => $config['refresh_token'],
    'expires_in' => -1
]);

Here I'm tricking the middleware it has acquired an access token which has expired, so that these conditions are met:

  • Inside OAuth2Handler::requestNewAccessToken I'm learning that a raw token must exist:
if ($this->refreshTokenGrantType && $this->rawToken && $this->rawToken->getRefreshToken()) {
  • Next in OAuth2Handler::getAccessToken:
if ($this->rawToken === null || $this->rawToken->isExpired()) {

For the expiration check to be evaluated to true, I'm setting the expiration to a date in the past via expires_in - it can't be the default 0, since isExpired won't allow it:

public function isExpired()
{
    return $this->expiresAt && $this->expiresAt < time();
}
@kamermans
Copy link
Owner

Hi @bogdanghervan, thanks for the question and context. Your assessment seems correct to me on all fronts, and I agree that there's probably a better way (particularly because your implementation makes assumptions about the library that could reasonably change).

I think this scenario is made unnecessarily complicated by the fact that you are not using a persistence provider, nor are you obtaining the initial key and refresh token using the library. In a more typical scenario, you would use a persistence provider and then use the library to get the initial token, then, when it expires, the refresh token would be used to retrieve a newer token, which would be saved to disk (or redis or something). This pattern would continue indefinitely until the refresh token was revoked. Also, by using persistence, you would be able to reuse the same token until it expires, instead of issuing a new token each time.

Are you able to share the name of a provider that behaves in this way (issuing a bad token with a good refresh token, or requiring your first token to be retrieved using a refresh token)? It would be good to understand how common this paradigm is.

I'm happy to pull in support for this type of oauth flow if you have an implementation pull request or suggestions. I'm not sure how practical it would be for me to write it without a way to test it, however.

@TMWagner
Copy link

@kamermans
I'm dealing with exactly the same issue. Thank you @bogdanghervan for the "fix".

Glad to share more details in PM.
2019-10-28_21-46-31

@TMWagner
Copy link

@kamermans Could you provide an example on how to do this? Seems like it is a less "fragile" approach to fixing the problem

I think this scenario is made unnecessarily complicated by the fact that you are not using a persistence provider, nor are you obtaining the initial key and refresh token using the library. In a more typical scenario, you would use a persistence provider and then use the library to get the initial token, then, when it expires, the refresh token would be used to retrieve a newer token, which would be saved to disk (or redis or something). This pattern would continue indefinitely until the refresh token was revoked. Also, by using persistence, you would be able to reuse the same token until it expires, instead of issuing a new token each time.

@TMWagner
Copy link

@bogdanghervan Can you post or send the full working example for your solution?

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants