Xero - beautiful accounting software

Xero Developer Help Center

Xero Developer Community

Community > API Authentication >

invalid_grant when refreshing a token

Started by Rangana Hewasiribaddana -   in API Authentication

We have 3 organisations which i have to connect to my app by making 3 individual oauth calls.

For each call my grants are"openid email profile accounting.transactions accounting.contacts offline_access". However the refresh token is only valid for 30 mins.

Attempting to refresh using this token always results in an invalid_token exception. 

At this point i need to re-login and allow/auth the app form Xero. Which is not practical as there are background jobs and other tasks that happens behind the scenes without any user interaction

Hi Rangana

Thanks for your post.

It sounds like you may be hitting an Invalid Grant error.

Refresh Tokens are valid for 30 days, however they also provide a 30 minute grace period where the same token can be used as many times as needed, in case the initial response containing your new Refresh and Access tokens is lost.

If you receive a Invalid Grant Error, the most likely cause will be that the Refresh token you're using is either invalid, expired or has previously been used outside of the 30 minute grace period.

To resolve this error, please ensure that you're using the new Refresh token provided each time you use a Refresh Token. e.g, you hand in Refresh Token A, and receive Token B. If 30 minutes pass, you must use Token B on your next Refresh.

If you continue to have issues, please raise a case with us on Xero Central or via api@xero.com and provide the Client ID for your app. We'll be more than happy to help.

Kind Regards


Matthew W Ramsay (Community Manager)  


I seem to be having the same problem using a Machine to Machine set up. At connection time my code checks the Access Token's expiration date/time against a stored value, and if it has expired (30 mins has passed) I then submit a request with grant type refresh_token, but I get 'Bad Request' error along with 'invalid grant'. My code seems to work fine in individual user OAuth2 situations, it's just the M2M side of things that keeps going wrong...

Reg Solution J  

Exactly the same thing is happening for me; also machine to machine. I'm using the most recent refresh token in all cases. It's not practical to manually connect and generate a fresh token multiple times a day.

Phil Warner  

Thanks for the reply Rangana. These are my scopes for the call:

openid profile email accounting.transactions accounting.settings offline_access

Phil Warner  

Hi everyone. I did resolve this in the end, and I think it was down to me not using UTC to calculate whether the token validity period had expired. (in my case the software, a windows client/server application) is running on a hosted windows server, and at this time of year, in the UK at least, the local server time and UTC differ.

Don't think I've expressed that very well, but the gist is to check that you're comparing like with like when it comes to dates/times.

Hope that helps.

Reg Jackson  

Thanks for the hint Reg. I'm still a little unsure about what's going on.

When I get the initial token it returns an expires_at value of 1659025434, which I convert to milliseconds. When I check to see if it's expired I make a call to refresh the token and then I get an invalid grant message. The expires_at value in this case is 'Thu Jul 28 2022 17:23:54 GMT+0100 (British Summer Time)', and I understand that the refresh token is valid for 60 days, so why won't it grant me another token?

I'm using xero_node version 4.20.1

Phil Warner  

I managed to fix this. I was expecting a session_state parameter in the refresh token, but there isn't one. As a result of this, I wasn't saving the new access token or refresh token to my database properly, and ended up trying to re-use what was an old refresh token on the next call, which triggered the invalid_grant message.

A bit silly, but posting here just to give others something else to check.

Phil Warner