7

I'm using Xero OAuth2.0 APIs, I am refreshing token once token is expired. Xero Documentation I'm storing token in JSON file so i can retrive next time.

Erorr Response:

{
"error": "invalid_grant"
}

Please refer below code i've used

public function getAccessToken($code = null) {
    if(file_exists($this->tokenPath) && isset($code)) {
        $accessToken = $this->getAccessTokenFromAuthCode($code);
    } else if (file_exists($this->tokenPath)) {
        $accessToken = $this->getAccessTokenFromJSON();
        try {
            if (time() > $accessToken->expires) {
                $accessToken = $this->provider->getAccessToken('refresh_token', [
                    'refresh_token' => $accessToken->refresh_token
                ]);
            }
        } catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
            //header('Location: ' . $this->getAuthorizationUrl());
        }

    } else if(isset($code)){
        $accessToken = $this->getAccessTokenFromAuthCode($code);
    } else {
        header('Location: ' . $this->getAuthorizationUrl());
    }

    return $accessToken;
}

public function getAccessTokenFromAuthCode($code) {
    return $this->storeAccessTokenToJSON($this->provider->getAccessToken('authorization_code', ['code' => $code]));
}

public function getAccessTokenFromJSON(){

    return json_decode(file_get_contents($this->tokenPath));
}

public function storeAccessTokenToJSON($accessToken){
    file_put_contents($this->tokenPath, json_encode($accessToken));

    return json_decode(file_get_contents($this->tokenPath));
}
Kirit
  • 405
  • 3
  • 18
  • Check if the configuration you have given in the app matches the configurations you used to generate the initial file. – Nayanajith Jun 27 '22 at 13:48

3 Answers3

3

The expiration for an access token is 30 minutes. And Unused refresh tokens expire after 60 days. If you don’t refresh your access token within 60 days the user will need to reauthorize your app.

  • If you perform a token refresh successfully you get a new refresh token with the new access token
  • If for whatever reason, you don't receive the response after performing the token refresh you can retry refreshing the old token for a grace period of 30 minutes
$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => "https://identity.xero.com/connect/token?=",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 0,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => array(
 'XXXXXXXXXXXXX','client_secret' =>
 'YYYYYYYYYYYYYYYYYYYYYYYYYYYYY'),
  CURLOPT_HTTPHEADER => array(
    "grant_type: refresh_token",
    "Content-Type: application/json",
     ),
));

$response = curl_exec($curl);

curl_close($curl);
echo $response;
Gokul
  • 1,130
  • 13
  • 18
0

Did you specify the 'offline_access' scope when you got your initial token?

https://developer.xero.com/documentation/guides/oauth2/scopes#offline-access

shagaroo
  • 21
  • 2
  • Please phrase this as an explained conditional answer, in order to avoid the impression of asking a clarification question instead of answering (for which a comment should be used instead of an answer, compare https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead ). For example like "If your problem is ... then the solution is to .... because .... ." – Yunnosch Mar 27 '22 at 20:30
-1

Invalid_grant is the standard error response code when a refresh token has expired.

Common token lifetimes are something like: * Access token = 60 minutes * Refresh token = 8 hours

When the refresh token expired you have to get the user to log in again.

Gary Archer
  • 22,534
  • 2
  • 12
  • 24
  • According to the docs, https://developer.xero.com/documentation/oauth2/auth-flow, "Your app can refresh an access token without user interaction by using a refresh token". This appears to be broken. – hamncheez May 03 '20 at 05:14