-
Notifications
You must be signed in to change notification settings - Fork 161
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
How to use in clustered node server (PM2)? #123
Comments
I have the same issue. Have you figured out a solution? We follow this process:
This works great in a single-node environment, but when this runs in a clustered environment, we see this error:
This is the relevant code: private async validateToken() {
// Need to double check if oauthClient is available when in multi-pod HA environment
if (!this.oauthClient) {
this.oauthClient = new OAuthClient({
clientId: environment.INTUIT_CLIENT_ID,
clientSecret: environment.INTUIT_CLIENT_SECRET,
environment: environment.INTUIT_ENV,
redirectUri: environment.INTUIT_REDIRECT_URI,
logging: true
});
}
const isTokenValid = await this.oauthClient.isAccessTokenValid();
if (isTokenValid) {
this.logger.log('Token is valid');
} else {
const testToken = await this.oauthClient.token.getToken();
if (!testToken.refresh_token) {
const dbdoc = await this.findToken(TOKEN_NAME);
this.token = dbdoc.token;
this.oauthClient.setToken(this.token);
const isValid = await this.oauthClient.isAccessTokenValid();
if (!isValid) {
await this.refreshToken();
}
} else {
await this.refreshToken();
}
}
}
private async refreshToken() {
await this.oauthClient
.refresh()
.then((res) => {
this.intuitTokenDto.token = res.token;
this.createOrUpdateToken({ name: TOKEN_NAME }, this.intuitTokenDto);
})
.catch((err) => {
const msg = 'Could not refresh access token. User must reauthenticate to Intuit for new token.';
err.error = msg;
throw err;
});
} |
Right now I just use a single server instance. :-/ I don't anticipate it being that bad for now because the proportion of users actually hitting QBO is very small -- just those with accounting privileges. Eventually I will revisit the clustered environment, and imagine that it will work by deeply serializing the oauthClient into a database or local json file, check if it is there, and reconstitute the oauthClient from that data if it is. I don't have the cycles for that at this time. It would be nice if the API had |
I treat the refresh_token as a single-use token. When a new access_token is obtained, I store the new access_token and refresh_token in a central database. In a cloud server environment where multiple instances of my program might attempt to access QuickBooks simultaneously, a race condition can occur. To address this, I serialize access to the stored refresh_token using Postgres. I store the tokens in a table row designated for each company_id and include a column that serves as a lock when refreshing the tokens. This ensures that only one process can refresh the tokens at any given time. While I have not extensively tested this solution in a production setting, it appeared to work effectively during the limited testing conducted before the project shifted away from QuickBooks. |
@abisalehalliprasan Do you know a workaround for this? |
I'm struggling trying to implement OAuth2 in a pm2 clustered environment. The example provided stores the new OAuthClient in a global variable. This is great if everyone is connecting to that one server instance. In production that is almost never the case.
I am going to assume that if process 1 and process 2 create wholly new OAuthClients, then access tokens returned to 2 will invalidate tokens in 1. Is that correct?
If so, I need a way to reconstitute an OAuthClient from data stored in a database. I imagine the flow will look like this:
The text was updated successfully, but these errors were encountered: