Zero-downtime OAuth client secret rotation for Embeddable Client App SDK

We’re approaching the 90-day window for our Genesys Cloud OAuth client secrets, and the standard procedure is causing a brief outage while we redeploy the Client App SDK wrapper to all agents. I want to avoid that. The documentation hints at having two active secrets to allow rotation without downtime, but the Client App SDK initialization doesn’t seem to have a built-in mechanism to pick between them dynamically based on a feature flag or similar.

My current setup uses a simple wrapper around the genesys-cloud-client-embed JS library. Here is the initialization logic:

import { createClient } from '@genesys/cloud-client-embed';

const initGenesysClient = async () => {
 const client = await createClient({
 region: 'us-east-1',
 clientId: process.env.GENESYS_CLIENT_ID,
 // This is the problem area. If I switch this env var, 
 // existing sessions might fail until they refresh?
 clientSecret: process.env.GENESYS_CLIENT_SECRET_OLD 
 });
 return client;
};

The plan is to:

  1. Generate a new client secret in the Developer Console.
  2. Update the app registration to have both the old and new secrets active.
  3. Flip a config flag to start using the new secret for new sessions.
  4. Wait for all old sessions to expire or refresh.
  5. Remove the old secret.

The issue is step 3 and 4. The SDK holds the token. If an agent has an active session initialized with the OLD secret, and the token expires, will the SDK attempt to refresh it using the OLD secret (which is still valid in Genesys until I remove it)? Or does it re-authenticate with the current clientSecret passed at init?

If it uses the init config, then agents need to hard refresh. I’d rather not force a hard refresh on 200 agents. Is there a way to inject the new secret into the refresh flow without re-initializing the whole client? Or am I missing a specific API endpoint to force a token refresh that picks up the new secret from the server side?

I’ve checked the genesys-cloud-client-embed source but it’s pretty opaque on the refresh logic. Any pointers?