-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Description
Before opening, please confirm:
- I have searched for duplicate or closed issues and discussions.
- I have read the guide for submitting bug reports.
- I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.
JavaScript Framework
Vue
Amplify APIs
Authentication
Amplify Version
v6
Amplify Categories
auth
Backend
CDK
Environment information
System:
OS: macOS 15.7.1
CPU: (12) arm64 Apple M2 Pro
Memory: 60.03 MB / 16.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 22.18.0 - /Users/ericaabbott/.nvm/versions/node/v22.18.0/bin/node
Yarn: 3.5.0 - /Users/ericaabbott/.nvm/versions/node/v22.18.0/bin/yarn
npm: 10.9.3 - /Users/ericaabbott/.nvm/versions/node/v22.18.0/bin/npm
pnpm: 10.20.0 - /Users/ericaabbott/.nvm/versions/node/v22.18.0/bin/pnpm
Watchman: 2025.02.10.00 - /opt/homebrew/bin/watchman
Browsers:
Chrome: 142.0.7444.60
Firefox: 132.0.2
Safari: 26.0.1
npmPackages:
@tsconfig/node22: ^22.0.2 => 22.0.2
@types/node: ^22.18.11 => 22.19.0
@vitejs/plugin-vue: ^6.0.1 => 6.0.1
@vue/tsconfig: ^0.8.1 => 0.8.1
aws-amplify: ^6.15.8 => 6.15.8
aws-amplify/adapter-core: undefined ()
aws-amplify/adapter-core/internals: undefined ()
aws-amplify/analytics: undefined ()
aws-amplify/analytics/kinesis: undefined ()
aws-amplify/analytics/kinesis-firehose: undefined ()
aws-amplify/analytics/personalize: undefined ()
aws-amplify/analytics/pinpoint: undefined ()
aws-amplify/api: undefined ()
aws-amplify/api/internals: undefined ()
aws-amplify/api/server: undefined ()
aws-amplify/auth: undefined ()
aws-amplify/auth/cognito: undefined ()
aws-amplify/auth/cognito/server: undefined ()
aws-amplify/auth/enable-oauth-listener: undefined ()
aws-amplify/auth/server: undefined ()
aws-amplify/data: undefined ()
aws-amplify/data/server: undefined ()
aws-amplify/datastore: undefined ()
aws-amplify/in-app-messaging: undefined ()
aws-amplify/in-app-messaging/pinpoint: undefined ()
aws-amplify/push-notifications: undefined ()
aws-amplify/push-notifications/pinpoint: undefined ()
aws-amplify/storage: undefined ()
aws-amplify/storage/s3: undefined ()
aws-amplify/storage/s3/server: undefined ()
aws-amplify/storage/server: undefined ()
aws-amplify/utils: undefined ()
npm-run-all-test: 0.0.0
npm-run-all2: ^8.0.4 => 8.0.4
typescript: ~5.9.0 => 5.9.3
vite: ^7.1.11 => 7.2.2
vite-plugin-vue-devtools: ^8.0.3 => 8.0.3
vue: ^3.5.22 => 3.5.24
vue-tsc: ^3.1.1 => 3.1.3
npmGlobalPackages:
corepack: 0.33.0
npm: 10.9.3
Describe the bug
When Amplify.configure() is called multiple times to switch the Auth.Cognito.userPoolClientId, the Auth.signIn() method correctly uses the new clientId.
However, the internal TokenProvider's TokenOrchestrator is not updated. It retains the stale, original clientId. This causes any subsequent call to refresh the token, either by fetchAuthSession({ forceRefresh: true }) or by the internal Amplify token refresh functionality to fail, as it sends the stale clientId to Cognito, which doesn't match the user's session.
To reproduce this, you need:
A single Cognito User Pool.
Two App Clients in that User Pool (e.g., CLIENT_ID_A and CLIENT_ID_B).
A test user that can log in to both.
Expected behavior
When the userPoolClientId is changed by calling Amplify.configure() multiple times, this userPoolClientId should be used when attempting to refresh the token
Reproduction steps
https://github.com/eabbott2b/amplify-configure-bug
Code Snippet
import { ref } from 'vue';
import { Amplify } from 'aws-amplify';
import { signIn, fetchAuthSession, confirmSignIn, type ConfirmSignInInput, type SignInOutput, type ConfirmSignInOutput } from 'aws-amplify/auth';
// --- 1. SET YOUR PREREQUISITES HERE ---
const REGION = 'your-region'; // e.g., 'us-east-1'
const USER_POOL_ID = 'your-user-pool-id';
const CLIENT_ID_A = 'your-first-app-client-id'; // The "stale" client
const CLIENT_ID_B = 'your-second-app-client-id'; // The "active" client
// -------------------------------------
const username = ref('test-user');
const verificationCode = ref('TestPassword123!');
const log = ref('');
const logMsg = (msg: string) => {
log.value += `[${new Date().toLocaleTimeString()}] ${msg}\n`;
};
/**
* STEP 1: Configure Amplify with Client A.
* This sets the internal TokenOrchestrator's config.
*/
function configureClientA() {
const configA = {
Auth: {
Cognito: {
userPoolId: USER_POOL_ID,
userPoolClientId: CLIENT_ID_A,
region: REGION,
},
},
};
Amplify.configure(configA);
logMsg(`Configured with CLIENT_ID_A: ${CLIENT_ID_A}`);
}
/**
* STEP 2: Re-configure with Client B and sign in.
* This proves that signIn() correctly uses the new config.
*/
async function configureClientB_and_SignIn() {
const configB = {
Auth: {
Cognito: {
userPoolId: USER_POOL_ID,
userPoolClientId: CLIENT_ID_B,
region: REGION,
},
},
};
Amplify.configure(configB);
logMsg(`Configured with CLIENT_ID_B: ${CLIENT_ID_B}`);
let signInOutput: SignInOutput | undefined
let confirmSignInOutput: ConfirmSignInOutput | undefined
logMsg('Attempting signIn with CLIENT_ID_B...');
try {
signInOutput = await signIn({
username: username.value,
options: {
authFlowType: 'CUSTOM_WITHOUT_SRP'
}
})
} catch (err) {
console.info('Sign in error:', err)
return
}
if (signInOutput?.nextStep?.signInStep === 'CONFIRM_SIGN_IN_WITH_CUSTOM_CHALLENGE') {
let confirmSignInInput: ConfirmSignInInput = { challengeResponse: verificationCode.value }
try {
confirmSignInOutput = await confirmSignIn(confirmSignInInput)
} catch (err) {
console.info('Confirm sign in error:', err)
}
}
if (signInOutput?.isSignedIn || confirmSignInOutput?.isSignedIn) {
logMsg('✅ signIn with CLIENT_ID_B SUCCEEDED.')
} else {
logMsg(`❌ signIn with CLIENT_ID_B FAILED.`);
}
}
/**
* STEP 3: Force a token refresh.
* This will fail because the internal TokenOrchestrator
* will use CLIENT_ID_A from Step 1.
*/
async function forceRefresh() {
logMsg('Attempting forceRefresh...');
logMsg('Open your Network tab to see the "GetTokensFromRefreshToken" request.');
try {
const session = await fetchAuthSession({ forceRefresh: true });
if (session.tokens?.accessToken) {
logMsg(`Access Token after refresh: ${session.tokens.accessToken}`);
} else {
logMsg('❌ No Access Token found after refresh.');
logMsg('\n--- FAILURE ANALYSIS ---');
logMsg(`The API call failed because the default TokenProvider ` +
`sent CLIENT_ID_A ("${CLIENT_ID_A}") in its refresh request, ` +
`but the refresh token was issued to CLIENT_ID_B ("${CLIENT_ID_B}").`);
}
} catch (e) {
logMsg(`❌ fetchAuthSession FAILED: ${e}`);
}
}Log output
[15:41:06] Configured with CLIENT_ID_A: [redacted]
[15:41:10] Configured with CLIENT_ID_B: [redacted]
[15:41:10] Attempting signIn with CLIENT_ID_B...
[15:41:11] ✅ signIn with CLIENT_ID_B SUCCEEDED.
[15:41:18] Attempting forceRefresh...
[15:41:18] Open your Network tab to see the "GetTokensFromRefreshToken" request.
[15:41:18] ❌ No Access Token found after refresh.
[15:41:18]
--- FAILURE ANALYSIS ---
[15:41:18] The API call failed because the default TokenProvider sent CLIENT_ID_A ("[redacted]") in its refresh request, but the refresh token was issued to CLIENT_ID_B ("[redacted]").
aws-exports.js
No response
Manual configuration
No response
Additional configuration
No response
Mobile Device
No response
Mobile Operating System
No response
Mobile Browser
No response
Mobile Browser Version
No response
Additional information and screenshots
This has only been an issue since updating from Amplify version 5.3.6 to 6.15.7/6.15.8. I haven't been able to the release where the issue was introduced