Google Plus API - Cannot Handle Token Prior to Certain Date - php

I implemented a login functionality using Google Plus API. It was working fine until we moved the deployment timezone. The problem below started appearing from time to time even though the server time has been adjusted properly:
Cannot handle token prior to 2018-02-01T06:30:07+0000
This was implemented in PHP and using the SDK for Google Plus. Has anyone encountered this before and resolved it properly?

This worked for me as well. I had to go into my vendor folder that composer generates for me in vendor\google\apiclient\src\Google\AccessToken\Verify.php and look for a function getJwtService() which should look exactly like this
private function getJwtService()
{
$jwtClass = 'JWT';
if (class_exists('\Firebase\JWT\JWT')) {
$jwtClass = 'Firebase\JWT\JWT';
}
if (property_exists($jwtClass, 'leeway')) {
// adds 1 second to JWT leeway
// #see https://github.com/google/google-api-php-client/issues/827
$jwtClass::$leeway += 1;
}
return new $jwtClass;
}
Then I changed the value of the $jwtClass::$leeway += 1; to $jwtClass::$leeway += 200; due to my timezone. I was about 2mins 30 seconds behind. Beware this comes with security vulnerabilities.

While the answer provided by richard4s works well but it's not a good practice to edit files in vendor directory as they are created by composer and would typically be outside your project's Git/Svn repo. The Google_Client accepts custom jwt object as a parameter to it's constructor. So here's a proper way to fix this:
$jwt = new \Firebase\JWT\JWT;
$jwt::$leeway = 5; // adjust this value
// we explicitly pass jwt object whose leeway is set to 5
$this->client = new \Google_Client(['jwt' => $jwt]);
Copied from this article.

This error appears to occur when the server's clock is a few seconds behind Auth servers clock. You probably have a slight skew between the clock on the server that mints the tokens and the clock on the server that's validating the token if the iat or nbf is in the future, then the token isn't yet valid.
One solution would be to use a small leeway, like this:
JWT::$leeway = 5; // Allows a 5 second tolerance on timing checks
see issue 1172

Related

Trying to add Google sign in api to octobercms

I'm using OctoberCMS based on Laravel freamwork.
I would like to have option on my website "sign in with google account".
So I went to https://developers.google.com/identity/sign-in/web/devconsole-project
and I fallowed all of the steps to "Authenticate with a backend server".
Becouse I don't have ssh access to my domain ( I cannot install library using Composer), so I downloaded Google API Client Library for php in .zip .
I unpacked it to 'plugins/nameOfMyplugin/google'.
And I got stuck,becouse I don't have any idea how to Send the ID token to my server and to validate it with those library, then I would like to create new user in my db if not exist in my rainlab.user.plugin.
Thank You for any help.
I have solved it.
In octoberCMS there is no reason for connect with google api by Your own, better solusion is download already made plugin(octobercms.com/plugin/flynsarmy-sociallogin) which is working.
I just downloaded octobercms.com/plugin/flynsarmy-sociallogin, but as I said it before, got some problems with login into my website.
I sow that each 12 minutes break between log out and log into my website I can login. When I tried to log into after in 11 minutes after log out it didn't work.
I went to my backend/ settings / logs /event logs and sow that
Cannot handle token prior to 2017-04-19T08:27:14+0000 in public_html/plugins/flynsarmy/sociallogin/vendor/firebase/php-jwt/src/JWT.php on line 124.
It's mean that my server time have 12 minutes late.
There are 2 ways to solve it:
First one not good for safety reasons:
SET in plugins/flynsarmy/sociallogin/vendor/firebase/php-jwt/src/JWT.php
public static $leeway = x;
Where x are secunds, in my example
or add difference of time in this if in from 123 :
if (isset($payload->iat) && $payload->iat > ($timestamp + static::$leeway +
**720**)) {
throw new BeforeValidException('Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->iat)
);
}
But as I said... it's not safety...
Second solution is to set time on server in right way.
There is a lot of solutions how to do it:
http://www.inmotionhosting.com/support/website/php/update-local-php-settings
https://help.directadmin.com/item.php?id=52
http://forum.directadmin.com/showthread.php?t=1817

Google PHP Api method takes very long to execute

I am working on a dynamic website, which relies heavily on ajax calls. I've noticed that when I load in my front page, and try to access the main search box on this page, it takes 5-7 seconds until the ajax request completes which populates the main search box. I've managed to figure out that delay is being caused by the Google API PHP Library, which starts as soon as the HTML of my page is loaded, to try to authenticate the visiting user. I've benchmarked the script in parts, and figured out, that the problem is in the "verifyIdToken" method of the library, which to complete, takes around 5 seconds.
I've noticed that in the documentation and tutorials, Google says: "The library will automatically download and cache the certificate required for verification, and refresh it if it has expired."
Does anyone know if:
this is the normal behaviour of this method, and it SHOULD take this long to execute?
the caching is the standard behaviour, or do I have to set it somewhere to actually cache the required data?
if it is the standard behaviour, how could I check if the caching actually happens or not?
Here is the full code I am working on, maybe someone spots an error in it:
$client_id='xxxxxx';
$client_secret='xxxxxxxx';
$client = new Google_Client();
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->setApplicationName("Converser Google API");
$client->addScope('https://www.googleapis.com/auth/plus.me');
$client->addScope('https://www.google.com/m8/feeds');
$client->addScope('https://mail.google.com/');
$client->addScope('email');
$client->setRedirectUri('postmessage');
$client->setAccessType("offline");
$client->setApprovalPrompt("force");
if (!isset($_SESSION['google-api']['access_token'])) {
if (isset($_REQUEST['code'])) g_exchangeCode($_REQUEST['code']);
else g_kill(0);
} else {
$accessToken=$_SESSION['google-api']['access_token'];
$client->setAccessToken($accessToken);
$returnData['auth_by']='token';
}
if($client->isAccessTokenExpired()) {
if (isset($_REQUEST['gid']) && !empty($_REQUEST['gid'])) g_refreshToken($_REQUEST['gid']);
else if (isset($_REQUEST['code']) && !empty($_REQUEST['code'])) g_exchangeCode($_REQUEST['code']);
else g_kill(1);
}
$token_data = $client->verifyIdToken()->getAttributes();
It's caused by ipv6, you need to use ipv4 or you get this error .
This commit allowed cURL options to be set through setClassConfig. Setting this should solve it.
'CURLOPT_IPRESOLVE', 'CURL_IPRESOLVE_V4'
If you are using master branch than checkout this.

PHPRedis - time() does not work

I have a problem.
In my project I have few servers which modify same data in redis.
All the servers may have different time.
In other words, I can't rely on app server time in some cases.
So I would like to use Redis time as general base point.
Everything could be fine, PHPRedis documentation says there is a function which does exactly what I need: time().
But here is a BIG surprise:
//... create connection etc...
var_dump($redis->time());
Output is:
bool(false)
The question is - what the hell is this?
Have you ever faced such a problem?
How can I get redis server time using it's functions?
Note: other redis functions work fine, I am able to read and write data. Connection is ok and is created correctly.
Got no help here.
As well as anywhere else.
So I needed to invent a walkaround...
Here is it, if someone needs it.
// Generate unique temporary key
$key = uniqid() . time();
// Take some random future TS
$future_ts = time() + 1000;
$redis->setex($key, time(), 5);
$redis->expireAt($key, $future_ts);
// This variable now contains what I need
$redis_ts = $future_ts - $redis->ttl($key);

'PPConnectionException' exception is thrown in PayPal adaptive Payment 'Pay' request

I have integrated PayPal adaptive payments in my one of the WordPress plugin. My functionality is fully ready and was working well till yesterday. However, when I started with a final testing, I got stuck with this exception -
PPConnectionException Object ( [url:PPConnectionException:private] => https://svcs.sandbox.paypal.com/AdaptivePayments/Pay [data:PPConnectionException:private] => [message:protected] => error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number
........) //I am just pasting necessary piece of error to understand the problem
I have used this library - https://github.com/paypal/adaptivepayments-sdk-php
I am testing it under sandbox environment.
The problem seems to have with OpenSSL or cURL.
I searched for the solution a lot but did not find any helpful answer.
I am also pasting a sample code below (this is for 'parallel' payment method, but neither this nor other methods work) -
require_once('../PPBootStrap.php');
require_once('../Common/Constants.php');
define("DEFAULT_SELECT", "- Select -");
if(isset($_POST['receiverEmail'])) {
$receiver = array();
/*
* A receiver's email address
*/
for($i=0; $i<count($_POST['receiverEmail']); $i++) {
$receiver[$i] = new Receiver();
$receiver[$i]->email = $_POST['receiverEmail'][$i];
/*
* Amount to be credited to the receiver's account
*/
$receiver[$i]->amount = $_POST['receiverAmount'][$i];
/*
* Set to true to indicate a chained payment; only one receiver can be a primary receiver. Omit this field, or set it to false for simple and parallel payments.
*/
$receiver[$i]->primary = $_POST['primaryReceiver'][$i];
}
$receiverList = new ReceiverList($receiver);
}
$payRequest = new PayRequest(new RequestEnvelope("en_US"), $_POST['actionType'], $_POST['cancelUrl'], $_POST['currencyCode'], $receiverList, $_POST['returnUrl']);
// Add optional params
if($_POST["memo"] != "") {
$payRequest->memo = $_POST["memo"];
}
$service = new AdaptivePaymentsService(Configuration::getAcctAndConfig());
try {
/* wrap API method calls on the service object with a try catch */
$response = $service->Pay($payRequest);
} catch(Exception $ex) {
require_once '../Common/Error.php';
/*******
***************************************************
PLEASE NOTE: the code is breaking here, an exception is thrown
***************************************************
*******/
exit;
}
$_POST data are passed from another file.
I have integrated the above code in my plugin (in WordPress way). In fact, if I run above functionality directly in a separate PHP file, even that does not work. So, its clear that the problem is something else. The problem seem to have with connection with PayPal and my server.
I am not getting, all the things were working till yesterday, but suddenly has stopped working. Also, nothing has been updated related to openssl, cURL or PHP on my server.
Any help would be greatly appreciated. Thanks !!!
EDIT:
Changing the openssl version number solves the issue. However, I am still concerned which among version number 1 and 4 is proper and will work in future.
Also, is there any security issue concerned when changing the value from 3 to something else?
If anyone could clarify this, it would be great. Thanks again.
I had the same problem. Seems as though PayPal made some changes yesterday in response to a security issue. Downloading the new version of PayPal PHP SDK that was just released should fix it
https://github.com/paypal/rest-api-sdk-php/releases/tag/v0.13.1
When I make any of the following change in the PPHttpConfig.php file, it works -
CURLOPT_SSLVERSION => 4
OR
CURLOPT_SSLVERSION => 1
2 doesn't work and 3 throws exception.
I am keeping version number 1 for now as I can see the version number 3 is replaced by 1 in the link shared by #Phil
I have also edited my answer for one more small query. If anyone could answer that, it would be great.
The security issue is the now infamous POODLE attack which makes SSLv3 totally insecure.
From the cURL source, you can see what the values mean (// comments mine):
enum {
CURL_SSLVERSION_DEFAULT, // 0, probably good
CURL_SSLVERSION_TLSv1, // 1, works
CURL_SSLVERSION_SSLv2, // 2, insecure
CURL_SSLVERSION_SSLv3, // 3, insecure
CURL_SSLVERSION_LAST /* never use, keep last */ // 4
};
Thus 1 means TLSv1 and as the comment says "never use", 1 is probably better than 4, and maybe 0 is better than 1 because it may try to use TLSv1 (or TLSv1.x or whatever comes default in future cURL versions).
However, I haven't tested 0 on multiple systems, and using the "default" SSL / TLS protocol version might mean SSLv3 instead of the latest and greatest and thus could not work, so YMMV.

PHP/Amazon S3: Query string authentication sometimes fails

I created a simple file browser in PHP that links to the files through generation expiring query URLs. So for each access to a directory, a link to each file is generated that is valid for say 900 seconds.
I now have the problem that the generated signatures seem to fail sometimes. Which is strange, since I intentionally used external S3 libraries for generating the URLs and signatures.
In fact, I tried the following libraries to generate the signatures:
CloudFusion
S3 generator
Amazon S3 PHP class
The libraries internally use hash_hmac('sha256', ... or hash_hmac('sha1', ... - I also don't understand why differnet hash algorithms are used.
Since the problem is the same with all libraries, it could as well be in my URL generation code, which is straightforward though:
$bucket = "myBucket";
$filename = $object->Key;
$linksValidForSeconds = 900;
$url = $s3->get_object_url($bucket, $filename, $linksValidForSeconds);
Sp $bucket and $linksValidForSeconds are constant, $filename is e.g. "Media/Pictures/My Picture.png". But event for same variables, it sometimes works, soemtimes doesn't.
Any ideas?
Edit: Typo/Wrong constant variable name fixed (thanks)
I found the problem and it had nothing to do with the code I mentioned. The generated URL is urlencode()'d and sent to another PHP script. There I use the URL to display an image from S3. I used urldecode() there to undo the changes but apparently this is not neccesary.
So each time the signature contains certain chars, the urldecode() would change them and corrupt it.
Sorry for omitting the actual problem code.
The code the asker is using above is from the CloudFusion AWS PHP SDK. Here's the documentation for get_object_url(): get_object_url ( $bucket, $filename, [ $preauth = 0 ], [ $opt = null ] )
The problem in your code above is your $linksValidForSeconds variable.
Where: $preauth - integer | string (Optional) Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with strtotime().
In other words, you are setting an expires time for 900 seconds after UNIX Epoch. I am honestly not sure how any links have worked using that library with your client code. If you are using the CloudFusion SDK, what you want to do is take the current UNIX time and add 900 seconds to that when passing in the parameter.
You seem to be confusing this with the Amazon S3 Class' getAuthenticatedURL method which takes the parameter integer $lifetime in seconds as you've used in your client code.
Be careful when using multiple libraries and swapping between them freely. Things tend to break that way.
The current version of CloudFusion is the AWS SDK for PHP, plus some other stuff. Amazon forked CloudFusion as the basis for their PHP SDK, then when the official SDK went live, CloudFusion backported the changes.
It's kind of a KHTML/WebKit thing. http://en.wikipedia.org/wiki/WebKit#History

Categories