As there are similar issues to mine, but still there is no fix and I get the following errors:
Type: Firebase\JWT\BeforeValidException
Message: Cannot handle token prior to 2019-05-13T10:46:12+0000
I had to set the leeway manually:
$jwt = new \Firebase\JWT\JWT;
$jwt::$leeway = 60;
Why this happens?
Can you share a code sample which tends to trigger the error? Is it persistent or intermittent?
@jdpedrie
require_once 'vendor/autoload.php';
// this solved the issue or with sleep(4);
$jwt = new \Firebase\JWT\JWT;
$jwt::$leeway = 60;
$client = new Google_Client(['client_id' => $CLIENT_ID]);
$payload = $client->verifyIdToken($id_token);
It is intermittent. It hasn't occurred before.
The error you see occurs when your local server time and the time of the server which created the JWT are not in sync. Your fix is correct, though setting it to 60 seconds is probably overkill. I'd try something like 5 or 10. Check your server, if you can, to see if the system clock is out of sync and whether that can be resolved. We try to fix this by setting the leeway to 1 second (unless you've already set it higher) in order to account for minor clock skew.
Other than setting the leeway to a high enough value, you could try wrapping the verify call in a try/catch and retrying a couple times if it fails.
Firebase\JWT\JWT::$leeway = 5;
do {
$attempt = 0;
try {
$payload = $client->verifyIdToken($id_token);
$retry = false;
} catch (Firebase\JWT\BeforeValidException $e) {
$attempt++;
$retry = $attempt < 2;
}
} while ($retry);
@jdpedrie Actually setting $leeway to 5 is ok for me (At least for now). Is there any issue for setting it to a bigger number? Also, I appreciate your solution (setting into while loop).
@jdpedrie Also I have another question. I think it is related to JWT's nbf key, isn't it? If yes, why google has set this key? Any reason?
Is there any issue for setting it to a bigger number?
Within reason a higher leeway won't have many practical issues. It's good practice to keep it as low as possible though. As you can see here, leeway is used for verifying expiration as well as not-valid-before. Therefore, the higher your leeway is set, the more likely it becomes that you'll grant access to your application using expired tokens.
I think it is related to JWT's nbf key, isn't it?
Yes, that is correct.
If yes, why google has set this key? Any reason?
I do not know the answer to this! I've seen several people say it's best practice to include, but not a ton of detail as to the specifics.
@jdpedrie Thank you for the explanation.
Once, I've asked a question about nbf in stackoverflow. One of the answers says that it relates to brute force attack. Not sure it's true.
The error you see occurs when your local server time and the Google auth server time are not in sync.
So, this happens when my local server time is greater that Google's? Yes?
We did a bit more thinking on this. None of the PHP libraries appear to set the nbf key in their JWTs. Assuming you're not making use of other language libraries, it's probably more likely that the issue arises from the iat key. As you see here, the errors are the same. You can verify this by pasting the JWT into the debugger at jwt.io. In any case, the solution remains the same.
So, this happens when my local server time is greater that Google's? Yes?
More correctly, I think, it occurs when the local time of the server which is verifying the token is earlier than the server which generated it. Earlier, I incorrectly called that the Google server (since corrected).
None of the PHP libraries appear to set the nbf key in their JWTs
Libraries that implement jwt can only ignore nbf or as you mentioned, iat. It's mostly related to the Google auth tokens that sets these keys to the token. The question is why do Google set these keys?
As described in my question in StackOverflow, one of the use cases of nbf is for example when an auction will start in the future. So users can't access to that resource to buy.
Btw, thank you. If you think this is not a real issue, feel free to close it.
I'm happy to continue trying to work it out if you have further questions. But how are you generating the JWT token? Have you attempted decoding it as I mentioned, to see whether it includes the nbf key?
@jdpedrie Thank you. I'll try to decode the JWT that provided by Google to see the details.
@vahidvdn I'm going to close this for now. If you have any more questions which might be outstanding, please feel free to re-open it!
Most helpful comment
The error you see occurs when your local server time and the time of the server which created the JWT are not in sync. Your fix is correct, though setting it to 60 seconds is probably overkill. I'd try something like 5 or 10. Check your server, if you can, to see if the system clock is out of sync and whether that can be resolved. We try to fix this by setting the leeway to 1 second (unless you've already set it higher) in order to account for minor clock skew.
Other than setting the leeway to a high enough value, you could try wrapping the verify call in a try/catch and retrying a couple times if it fails.