Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refreshAccessToken doesn't check {"error":"invalid_grant"} response and sets both tokens to undefined #171

Open
darkman82 opened this issue Feb 17, 2021 · 4 comments

Comments

@darkman82
Copy link

Sometimes, when refreshing the access token, QB responds with this body {"error":"invalid_grant"} which is accepted as a successful response and leads to both tokens being set to undefined.

A this point the qbo object becomes useless and you need a new one.

e : null
r : {"error":"invalid_grant"}

index.js#L146

    request.post(postBody, (function (e, r, data) {
        if (r && r.body) {
            var refreshResponse = JSON.parse(r.body);
            this.refreshToken = refreshResponse.refresh_token;
            this.token = refreshResponse.access_token;
            if (callback) callback(e, refreshResponse);
        } else {
            if (callback) callback(e, r, data);
        }
    }).bind(this));

@lukas1994
Copy link

  const oauth = getOAuthClient();
  oauth.setToken(token);
  const authResponse = await oauth.refresh();
  const newToken: QuickBooksToken = authResponse.token;

  // https://help.developer.intuit.com/s/article/Validity-of-Refresh-Token
  if (newToken.refresh_token !== token.refresh_token) {
    // save new token
  }

I use this code but quite often I'm also hitting the invalid_grant issue. Then my users need to go through the oauth process again.

I feel like I'm doing what's described here.

Has anyone figured out a good solution?

@darkman82
Copy link
Author

darkman82 commented Feb 17, 2021

To be clear: I don't use oauth, I used it once in the QB Playground just to get the refreshToken, which is supposed to last 100 days, then I keep it updated when it changes across the refresh processes.

The invalid_grant error does NOT invalidate the current refreshToken (if you updated it from the previous successful request), this means that it can be used again to get a new access token (=> you don't need to OAuth again).

The problem is that, bug or not, invalid_grant error, and any others, are not handled at all, leading to both tokens being set to undefined.

The solution is: check if the "error" field is present in the body response and, in case, avoid updating the token variables with undefined. Ignore it and retry after a while.

PS: the reason why I get invalid_grant error is related to the asynchronous logic behind my invoicing system which leads to pseudo-concurrent refresh requests. I would probably need to convert some array.forEach (async) to a for-of loop (synchronous).

@aniespica
Copy link

@darkman82 Have you figured out how to solve this?

@darkman82
Copy link
Author

As I said, I got the error due to concurrent API calls, so I moved to synchronous logic and it worked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants