-
Notifications
You must be signed in to change notification settings - Fork 159
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
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: