Norman Firkins Posted August 4, 2021 Share Posted August 4, 2021 Hi there, My OAuth2.0 code has been working fine, but today I have received this from my API: {'error': 'invalid_grant', 'error_description': 'the submitted refresh_token is invalid'}. The refresh token had been minted a few minutes before from a sign in via Sage to authorize my app, so I doubt that my refresh token has expired. Any ideas on what the problem could be? Here is my code to make sure I've followed the documentation correctly; url = 'https://oauth.accounting.sage.com/token' payload = {'grant_type': 'refresh_token', 'refresh_token': refreshtoken, 'client_id': client_id, 'client_secret': client_secret } headers = { 'Content-Type': 'application/x-www-form-urlencoded' } response = requests.request("POST", url, headers=headers, data=payload) Thank you any help would be great Link to comment Share on other sites More sharing options...
Steel, Mark Posted August 5, 2021 Share Posted August 5, 2021 Hi Norman, thank you for your question. We're not aware of any issue with the exchange of refresh_tokens at present. How are you storing the access and refresh tokens? Do you set a timer for the access_token period or are you exchanging refresh_tokens for every request? Making a comparison of your code to code I use to exchange refresh tokens, I noticed that I am also setting the below in the request header. 'Accept': 'application/json' Thanks Mark Link to comment Share on other sites More sharing options...
Norman Firkins Posted August 5, 2021 Author Share Posted August 5, 2021 Hi @Steel, Mark, I'm exchanging refresh_tokens for every request. I added the accept parameter to the header and it works, thank you so much. I don't believe that was in the documentation though for Authorization? It would be helpful to have that in the documentation, especially for newbies to the Accounting API, as I was following the documentation strictly. Or does the documentation just assume that you know to put that in the header? Thanks again. Link to comment Share on other sites More sharing options...
Norman Firkins Posted August 5, 2021 Author Share Posted August 5, 2021 @Steel, Mark I thought it was working, but I have left it for about 4 hours now and have ran my program again and the problem is still there. Refresh tokens are valid for 31 days aren't they? So why would it be saying that a token is invalid? Also my token is stored in a variable, that takes the refresh token directly from the JSON response Link to comment Share on other sites More sharing options...
Steel, Mark Posted August 6, 2021 Share Posted August 6, 2021 Thanks Norman Refresh tokens are valid for 31 days or until a new refresh token is requested. If you had a scenario where many requests were made consecutively you would be requesting a new access_token for each of those requests. How do you ensure you wait for the new access_token and refresh_token to be returned and the holding variable set before making the next request? It sounds as if you're trying to exchange an already super-seeded refresh_token which is being seen as invalid. There's Java Script in the Demo Data Postman collection, that uses a timer to understand when the current access_token is due to expire and then exchanges the refresh_token before it expires and makes the next request. I've included the script below FYI. // Global variables const moment = require ('moment'); var time = moment(); if (pm.environment.get("accessTokenExpires")< time.format()) { pm.sendRequest({ url: 'https://oauth.accounting.sage.com/token', method: 'POST', header: { 'Accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded', }, body: { mode: 'urlencoded', urlencoded: [ {key: "client_id", value: pm.environment.get('clientId'), disabled: false}, {key: "client_secret", value: pm.environment.get('clientSecret'), disabled: false}, {key: "grant_type", value: "refresh_token", disabled: false}, {key: "refresh_token", value: pm.environment.get('refreshToken'), disabled: false} ] } }, function (error, response) { if(error===null){ pm.environment.set("accessToken", response.json().access_token); //set the Access token expiry time as the response time + 5 mins var tokenExpires = new Date; tokenExpires = time.add(5, 'minutes').format(); pm.environment.set("accessTokenExpires", tokenExpires); pm.environment.set("refreshToken", response.json().refresh_token); } }) 1 Link to comment Share on other sites More sharing options...
Recommended Posts
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now