We are building a custom agent desktop using the Genesys Cloud JavaScript SDK. The app handles token refresh automatically when the access token expires. The flow works fine in local development but fails in our production environment hosted on AWS EC2 instances in us-west-2.
The issue is that the server clock seems to be slightly ahead of the Genesys Cloud servers. When the SDK refreshes the token, it gets a new access token with an exp claim. However, the server clock is about 2 seconds ahead, so when the SDK immediately tries to use the new token, the Genesys API rejects it because it thinks the token is expired or not yet valid.
Here is the refresh logic we are using:
const refreshResponse = await platformClient.oauth.refreshToken(refreshToken);
const newAccessToken = refreshResponse.body.access_token;
// We store the token and immediately make a request
const users = await platformClient.users.getUsers();
The getUsers call returns a 401 Unauthorized error. The error message from the API is:
{"status":401,"code":"unauthorized","message":"Access token expired or invalid"}
I have checked the exp claim in the new token. It is set to 1715623000. The current time on our server is 1715623002. The Genesys Cloud servers are likely at 1715623000 or 1715623001. This 2-second difference causes the validation to fail.
We have tried adding a small delay after the refresh, but that feels like a hack. We also tried setting the ClockSkew property in the SDK configuration, but I cannot find the exact property name in the TypeScript definitions.
Is there a way to configure the SDK to handle clock skew? Or should we be adjusting the server time? We are using the @genesyscloud/platform-client-sdk version 2.5.0. Any help would be appreciated.
Clock skew is a nasty one. The JWT validation in the Genesys Cloud gateway is strict. If your server time is even 60 seconds ahead, the token appears expired before it actually is. You’ll get 401s immediately after refresh because the exp claim looks like it’s in the past relative to your clock.
The quick fix is to sync your EC2 instances with NTP. Run this on your instances:
Verify the drift with chronyc tracking. You want offset close to 0.
If you can’t control the server time directly or need a buffer for distributed systems, use the clockTolerance option in the SDK. This tells the client to ignore small discrepancies during token validation.
This adds a buffer to the expiry check. It doesn’t fix the root cause, but it stops the immediate 401s. Just remember that clockTolerance only helps the SDK validate the token locally. If you’re making direct REST calls without the SDK handling auth, you still need accurate time.
Also check your AWS IAM roles. Sometimes permission issues mask as auth errors if the SDK fails silently during refresh attempts. But in your case, the “immediately after refresh” symptom points straight to time sync.
Don’t rely on clockTolerance for long term. It’s a band-aid. Fix the NTP config. The gateway won’t care about your tolerance settings when you hit API endpoints directly with cURL or Postman. Those tools don’t have the SDK’s built-in skew handling.