Storing the Google OAuth Authorization Token in Database - php

I am building a portal where multiple users can log in to their multiple Gmail accounts. I have successfully retrieved the token value, However, I want to store that in my database but I am unable to store it.
Below is the code I am using:
function mInititalize(){
$client = new Google_Client();
$client->addScope('https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email https://mail.google.com/');
$client->setClientId(Config('gmail.client_id'));
$client->setClientSecret(Config('gmail.client_secret'));
$client->setRedirectUri('http://localhost:81'.Config('gmail.redirect_url'));
$loginURL = $client->createAuthUrl();
return redirect($loginURL);
}
After Redirection or user login
function mGetToken(){
$token = $client->fetchAccessTokenWithAuthCode( 'code'); // here i get the 'code' from login URL
I pass this code to get token I successfully get token
$oAuth = new Google_Service_Oauth2( $client);
$userData = $oAuth->userinfo_v2_me->get(); // get current user detail
}
I want to store $token value in database, but I am getting error message
>Serialization of 'Closure' is not allowed
Please anyone help me to solve this issue. Thanks.

I would suggest storing OAuth credential information for the Google API, not in your database, but through the API itself. If you're intending to use it any authentication manner, you'll run into problems, as the docs state:
Access tokens periodically expire and become invalid credentials for a related API request. Google Identity Platform: Using OAuth 2.0 for Web Server Applications
But, the same docs also show a way that you can set or retrieve the token natively within the API. Since it's data relating to google's auth'ing process, and since it might go stale if you store it, it seems best to just let them handle it and work with the API. The same source:
If you need to apply an access token to a new Google_Client object—for example, if you stored the access token in a user session—use the setAccessToken method:
$client->setAccessToken($access_token);
$client->getAccessToken();

Related

"unauthorized_client" error when using PHP client to refreshToken with Google API client?

I am requesting access to the user's data from an IOS app using this code from the GoogleSignIn pod
[GIDSignIn sharedInstance].uiDelegate = self;
[[GIDSignIn sharedInstance] setScopes:#[ ... ];
[[GIDSignIn sharedInstance] signInSilently];
I then receive the accessToken and the refreshToken in the appDelegate and I send that to the server running PHP and using this google client library (https://github.com/googleapis/google-api-php-client) ... for the first hour everything is working fine and the access token is valid and allowing me access to all the scopes. Then after an hour the access token expires and I try to refresh it using this code
$client = new Google_Client();
$client->setApplicationName(<app name>);
$client->setDeveloperKey(<google_oauth_developer_key>);
$client->setClientSecret(<google_oauth_client_secret>);
$client->setClientId(<google_oauth_client_id>);
$client->refreshToken("1/12ju3ZZim-r6co195lIVNNvzBq9x5G64GJCWkYsOQ18");
and the "refreshToken" function above returns this error
=> [
"error" => "unauthorized_client",
"error_description" => "Unauthorized",
]
It's worth noting that the app name, google_oauth_developer_key, google_oauth_client_secret, and google_oauth_client_id have not changed. They are the same ones that were working earlier to retrieve the user's contacts, calendar events, etc when the access token was not yet expired.
What could be causing this error?
You need to actually use your refresh token at some point.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
$client->getAccessToken();
Code ripped from my Oauth2Authentication.php sample
Note
Also remember that refresh tokens are user / client based. So if the token was generated by one client then a different client will probably not be able to use it. I will be very surprised if you can use a refresh token created in Ios code in a php application. The client types are different.
Ok so I figured out what I did wrong. I originally followed these instructions https://developers.google.com/identity/sign-in/ios/sign-in which assume you need online access only, but I actually need offline access to the scopes so I followed these instructions https://developers.google.com/identity/sign-in/ios/offline-access and it works now. So instead of having the IOS app send up the access token and the refresh token separately like this
- (void)signIn:(GIDSignIn *)signIn didSignInForUser:(GIDGoogleUser *)user
withError:(NSError *)error {
if (!error) {
NSString *accessToken = user.authentication.accessToken;
NSString *refreshToken = user.authentication.refreshToken;
I simply have it send up the serverAuthCode like this
- (void)signIn:(GIDSignIn *)signIn didSignInForUser:(GIDGoogleUser *)user
withError:(NSError *)error {
if (!error) {
NSString *serverAuthCode = user.serverAuthCode;
and then on the server I run this code to get the access token
$access_token = $client->authenticate($google_server_auth_code);
$client->setAccessToken($access_token);
and then when the access token expires I run this to refresh it
$access_token = $client->refreshToken($client->getRefreshToken());
$client->setAccessToken($access_token);

How can I re-acquire a Shopify OAuth access token for a store that has previously installed my application?

I requested authorization for a public application to be able to access store data via the Shopify API.
The store successfully authorized my application via an authorization request URL such as
https://some-store.myshopify.com/admin/oauth/authorize?client_id=123abc&scope=read_inventory%2Cread_products&redirect_uri=http%3A%2F%mysite.com%2Fauth.php&state=123456
and the response was passed back to my application. This response (containing the code that can be exchanged for a permanent access token) was mishandled by my application (an error on the page meant that the access token was not stored).
Everything I read regarding requesting these tokens involves authorization by the store - but given the store has already authorized my application, passed back the code and that code has already successfully been exchanged for a token: is there a way my application can request that same token or a fresh one using my API keys given that the application is already authorized?
The only method I currently can find for requesting a token requires starting back at the beginning and fetching a code for exchange etc.
I working in PHP and using Luke Towers' php shopify wrapper
This stage was completed successfully:
function check_authorization_attempt()
{
$data = $_GET;
$api = new Shopify($data['shop'], [
'api_key' => '123',
'secret' => '456',
]);
$storedAttempt = null;
$attempts = json_decode(file_get_contents('authattempts.json'));
foreach ($attempts as $attempt) {
if ($attempt->shop === $data['shop']) {
$storedAttempt = $attempt;
break;
}
}
return $api->authorizeApplication($storedAttempt->nonce, $data);
}
$response = check_authorization_attempt();
and I would have been able to read the access token from :
$access_token = $response->access_token;
But this was the stage at which my application hit an error in accessing a database in which to write said token.
I cannot repeat it without repeating the auth request because the data in $_GET that's passed to this function comes from Shopify's response to the shop owner authorizing the access, and includes amoung other things the code for exchange.
You have to re-ask for authorization. It is no one's fault but yours that your persistence layer code was incorrect. So there is nothing you can do to change that. Ensure your code works. Since the client has no token in your App persistence layer, your App will retry the authorization token exchange. They do not have to delete your App first. So basically, the next time your client tries to use the App, YES they will asked to approve it, but who cares, they will, and you'll get a good auth token to store. You have fixed your code (right), so that will work. You are one step closer to glory.
Shopify does return the Permanent Access Token, but the ACCESS_MODE must be "Offline" for the token to be permanent.
With ACCESS_MODE offline, your app receives the permanent access token
to make requests whenever you want, without the user's permission.
Documentation:
https://shopify.dev/tutorials/authenticate-with-oauth#step-2-ask-for-permission
https://shopify.dev/concepts/about-apis/authentication#api-access-modes

Change scope while issuing new access token when client sends valid refresh token

I am using php oauth2 library from this github repo.
PHP oauth2 library
Whenever i send a refresh token, I receive new access token with old scopes.
But i want to change the scopes returned with new access token.
When i first generate a token using user credentials grant type, I get the supported scopes for the user and store them this way.
$defaultScope = implode(" ", $scopes);$memory = new OAuth2\Storage\Memory(array('default_scope' =>$defaultScope));
$scopeUtil = new OAuth2\Scope($memory);
$this->server->setScopeUtil($scopeUtil);
$this->server->handleTokenRequest(OAuth2\Request::createFromGlobals())->send();
where $scopes is an array
for example $scopes=array("ADDUSER","EDITUSER","EDITROLE");
similarly , if i send refresh token using refresh_token grant type and run this with modified $scopes
for example $scopes=array("ADDUSER", "EDITROLE");
$defaultScope = implode(" ", $scopes);$memory = new OAuth2\Storage\Memory(array('default_scope' =>$defaultScope));
$scopeUtil = new OAuth2\Scope($memory);
$this->server->setScopeUtil($scopeUtil);
$this->server->handleTokenRequest(OAuth2\Request::createFromGlobals())->send();
I receive same old scopes("ADDUSER EDITUSER EDITROLE") which were set when new access token generated using user credentials grant type.
SO is there a way to change scopes when new access token is generated using refresh token ?
or am i doing something wrong here?
A Client can "down-scope" when it asks for a new access token in the refresh token grant, see the documentation around scope in the spec here: https://www.rfc-editor.org/rfc/rfc6749#section-6 Yet your Authorization server may or may not support that.

Make Oauth API calls with existing Access Token and Access Token Secret

I am using the Lusitanian PHP Oauth library (https://github.com/Lusitanian/PHPoAuthLib).
After the user gets authorized in my application, i have received values of Access Token and Access Token Secret. Now with these values, i would like to make authenticated calls to API. How can i make the calls with the values of Access Token, Access Token Secret, along with the values of Consumer Key and Consumer Secret? I don't want to get the user authorized every time, to make API calls for him. Does anyone have an idea ?
My request goes like this:
$result = json_decode( $service->request( '/users/getDetails' ), true
);
I have tried the REST Client of Firefox and Advanced REST Client of Chrome, that perform OAuth calls successfully, with just the values of Access Token, Access Token Secret, Consumer Key and Consumer Secret.
Similarly, i would like to perform the OAuth calls from my PHP code. The library which i am using, depends on Session to store these values (which requires the user to login each time) and build the Authorization header and signature. Is there a way i can build the Signature and Authorization header from my end manually and make the OAuth calls ?
Finally, i have tweaked the functionality of reusing the access tokens.
I am fetching token from a config php file, after i store the token in it.
The token can also be stored in a local PHP session and read from it.
The code for storing token is in Service/AbstractService.php:
$this->storage->storeAccessToken($this->service(), $token);
You can modify it like the following, to store the token in a session variable:
if(!isset($_SESSION['access_token'])) {
$token = new StdOAuth1Token();
$token->setRequestToken($access_token);
$token->setRequestTokenSecret($access_token_secret);
$token->setAccessToken($access_token);
$token->setAccessTokenSecret($access_token_secret);
$token->setEndOfLife(StdOAuth1Token::EOL_NEVER_EXPIRES);
$_SESSION['access_token'] = serialize($token);
}
Then when making a request to API, you can modify the code in request() function to use token from your session:
Change:
$token = $this->storage->retrieveAccessToken($this->service());
To:
$token = unserialize($_SESSION['access_token']);
This way, i could use custom PHP sessions to store and retrieve access tokens. You can also use Database or a text file to store and retrieve the tokens. It works! Hope it would be useful for someone.

Google PHP SDK - not getting refresh token

I am trying to get a refresh token for the Google API's, using the PHP SDK. I am authenticating the user with Javascript, retrieving a code, and exchanging it for an access_token server side, but this doesn't grant me an access token. What am I doing wrong? Here is the code I use:
$client = new Google_Client();
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->addScope('https://www.googleapis.com/auth/plus.me');
$client->addScope('https://www.google.com/m8/feeds');
$client->setRedirectUri('postmessage');
$client->setAccessType('offline');
if (isset($_REQUEST['code'])) {
$client->authenticate($_REQUEST['code']);
if ($client->getAccessToken()) {
$_SESSION['access_token'] = $client->getAccessToken();
$token_data = $client->verifyIdToken()->getAttributes();
$result['data']=$token_data;
$result['access_token']=json_decode($_SESSION['access_token']);
}
}
debug($result); //my own function, var_dumps the content of an array
Here is the result of the array:
$result['access_token'] contains:
access_token: TOKEN
created: 1434380576
expires_in: 3594
id_token: IDTOKEN
token_type:"Bearer"
If I am not mistaken the first access token should also contain the refresh token, what am I doing wrong?
First check the settings in the developer console of Google to see if your RedirectUri is the same and that the API is activated (although if you already got that .json, then I assume it is.
You have to go through the Google Auth Prompt Screen at least 1 time to get a refresh token in your .json, and if your RedirectUri is taking you nowhere, you won't be able to get your refresh token or even the access validated.
You can also try a service account if you're doing small file transactions and don't need a user validation for the process of your script. Good Luck.
The problem was that I had to specify that I want offline access in the authentication process, the client side... The Google API's are horribly documented!!!

Categories