Comments (5)
@kamermans Amazing - thank you so much for this thorough example! I really appreciate it. And I understand it - my mistake was in the "new OAuth2Middleware" - I did not realize I could/should pass it both grant types in one call. That's the missing link! Thank you again so much for the explanation and creating this library.
from guzzle-oauth2-subscriber.
Sure thing! It took me a while to wrap my head around it again, but I'm glad I finally did. I'm updating the README so it is more clear to the next person :)
from guzzle-oauth2-subscriber.
Hi @thebordella, I agree with you, it sounds like the RefreshToken
is not being used. I would need to be able to reproduce the issue myself to be able to easily debug it, but from what I can tell, you're using the refresh token part correctly. It looks like Google uses OAuth 2 with refresh tokens, so I'll see if I can test it out there, but it will take me at least a few days to find time.
In the meantime, perhaps you can come up with some shareable example that reproduces the problem?
from guzzle-oauth2-subscriber.
Thanks for your reply, @kamermans. One thing that confuses me is, in my latter code block, when new RefreshToken is assigned to $grant_type, how does it know where to get the persisted refresh token from? That is, it doesn't yet know about my custom persistence routine ... does it? This is unclear to me.
I added some debugging output to the OAuth2Handler.php script and it seems that "refreshTokenGrantType" remains null when my code block runs. When it detects that the auth token has expired and invokes requestNewAccessToken(), $this->refreshTokenGrantType is null. I'm not sure if that gives any clues...
from guzzle-oauth2-subscriber.
Hi @thebordella, sorry for the delayed response!
I have recreated a scenario similar to yours using the Google OAuth2 playground.
Please take a look at this script:
<?php
use kamermans\OAuth2\GrantType\RefreshToken;
use kamermans\OAuth2\GrantType\PasswordCredentials;
use kamermans\OAuth2\Persistence\TokenPersistenceInterface;
use kamermans\OAuth2\Token\TokenInterface;
use kamermans\OAuth2\OAuth2Middleware;
use GuzzleHttp\HandlerStack;
require_once __DIR__."/../guzzle_environments/6/vendor/autoload.php";
// Create a persistence provider that tells me what it's doing for debugging
class CustomTokenPersistence implements TokenPersistenceInterface {
private $file = "/tmp/token.txt";
public function saveToken(TokenInterface $token) {
echo "Saving token: ".var_export($token, true)."\n";
$value = $token->serialize();
file_put_contents($this->file, json_encode($value));
}
public function restoreToken(TokenInterface $token) {
$value = @file_get_contents($this->file);
$value = $value === false? null: $token->unserialize(json_decode($value, true));
echo "Restoring token: ".var_export($token, true)."\n";
return $value;
}
public function deleteToken() {
echo "Deleting token\n";
@unlink($this->file);
}
}
// Authorization client - this is used to request OAuth access tokens
$reauth_client = new GuzzleHttp\Client([
// URL for access_token request
'base_uri' => 'https://www.googleapis.com/oauth2/v4/token',
// 'debug' => true,
]);
$reauth_config = [
// PasswordCredentials credentials
"username" => "my-username",
"password" => "my-password",
// RefreshToken credentials
"client_id" => "my-client-id",
// You probably don't have an existing refresh token, but if you do you can put it here,
// otherwise just ignore this line or leave the value empty
"refresh_token" => "existing-token-if-available",
];
$token_persistence = new CustomTokenPersistence();
// This grant type is used to get a new Access Token and Refresh Token when
// no valid Access Token or Refresh Token is available
$grant_type = new PasswordCredentials($reauth_client, $reauth_config);
// This grant type is used to get a new Access Token and Refresh Token when
// only a valid Refresh Token is available
$refresh_grant_type = new RefreshToken($reauth_client, $reauth_config);
// Tell the middleware to use the two grant types
// Note that the second argument ($refresh_grant_type) gets stored in the OAuth2Handler
// as $this->refreshTokenGrantType, which explains why it was previously null.
$oauth = new OAuth2Middleware($grant_type, $refresh_grant_type);
// Setup persistence
$oauth->setTokenPersistence($token_persistence);
// Add the middleware to the HandlerStack
$stack = HandlerStack::create();
$stack->push($oauth);
// This is the normal Guzzle client that you use in your application
$client = new GuzzleHttp\Client([
'handler' => $stack,
'auth' => 'oauth',
]);
// This Google Cloud Platform endpoint will list all the projects you have access to
$endpoint_url = 'https://cloudresourcemanager.googleapis.com/v1/projects';
$response = $client->get($endpoint_url);
echo $response->getBody();
Note that the script above doesn't work correctly with Google Cloud Platform since they do not support the
PasswordCredentials
grant type, but I modified it to match your needs. If you do want to try this with GCP, go to the GCP OAuth 2.0 Playground, get a refresh token and put it in the$reauth_config
above, or stick it into your persisted object manually.
The script above can be used to setup your Guzzle client. Here's how it works in your application:
- The first time you run it, if there is no access token or refresh token, it will use the
PasswordCredentials
to retrieve an access token. Assuming this token came with a refresh token, that token will be saved in the persistence provider with the access token. - The next time the script is run, the access token and will be restored from persistence and will be used.
- Once the access token expires or is rejected by the server, the refresh token will be restored from persistence and the
RefreshToken
grant type will be used to obtain a new access token and refresh token, and these will be persisted together.
If you want to force the refresh token to be used the first time Guzzle is called after the script is run (without trying the old access token first), you could delete the contents of accessToken
in the persisted array when the script starts - that will force the access token to be invalid and the refresh token will be used to get a new access token.
from guzzle-oauth2-subscriber.
Related Issues (20)
- Comprehensive example of the Authorization Code Grant Type? HOT 6
- Client Credentials issue
- Unable to request new access token but manually set access token works
- Unable to get "Client Scoped Token"
- What is the best way to handle temporary failure on refreshing token? HOT 4
- it is not compatible with guzzle >=6 HOT 5
- It seems not possible to forward custom Guzzle options to the handler HOT 1
- TokenPersistenceInterface->restoreToken always called with new RawToken HOT 4
- Question: How to use Client Credentials and Refresh Token. Possibly missing Signer?
- Guzzle 8: The getConfig Method from ClientInterface will be removed HOT 6
- Guzzle 7 Uncaught Error: Call to undefined function GuzzleHttp\Psr7\stream_for() HOT 4
- Allow custom headers for OAuth requests HOT 2
- Token deleted before the new one is confirmed HOT 1
- Adding some content in the request body on access token retrieval HOT 2
- Deprecation notice about return type of several methods of the Collection class
- incompatible with guzzlehttp/guzzle 7.7.0 along with guzzlehttp/promises 2.0.0 HOT 6
- Get Token Payload HOT 1
- PHP 8.1 show user deprecated warnings on return types HOT 6
- Return type of the restoreToken function, in the TokenPersistenceInterface can't be null HOT 1
- Fitnesssync oauth uses a redirect to get code - how do I get the code other than manually?
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from guzzle-oauth2-subscriber.