How did you install the Amplify CLI?
npm
What version of Node.js are you using?
v24.11.1
What version of Amplify CLI are you using?
14.2.5 (regression introduced in v14.2.2 by PR #14315, still present as of 14.2.5)
What operating system are you using?
macOS
Did you make any manual changes to the cloud resources managed by Amplify? Please describe the changes if any.
No
Describe the bug
Three cascading bugs in the MFA role assumption credential caching logic were introduced by commit 04f7bcfc24 (PR #14315, fixing #14290 "role assumption through profiles not working properly"). These bugs cause MFA-based role assumption to fail with the error Resolved credential object is not valid.
Bug 1: MFA prompt never appears
getCachedRoleCredentials() always returns an object { credentials: {} } even when no valid cached credentials exist. This causes the check if (!roleCredentials) in getRoleCredentials() to always be false, so the STS AssumeRole call with MFA token is never executed.
Bug 2: Credential cache validation always fails
Credentials are cached in nested format { credentials: { accessKeyId, ... } } but validateCachedCredentials() expects flat format { accessKeyId, ... }. This causes cache validation to always fail, prompting for MFA on every CLI call.
Bug 3: identity.expiration.getTime is not a function error
When credentials are read from the JSON cache file, the Date object for expiration is deserialized as a string. The AWS SDK's @smithy/core module calls expiration.getTime() which fails on a string.
The fix in PR #14315 only addressed this in getConfiguredAWSClientConfig(), but getProfiledAwsConfig() is called directly during amplify env checkout without going through that code path.
Expected behavior
- When no valid cached MFA credentials exist, the user is prompted for their MFA token
- After successful role assumption, credentials are cached and reused until they expire
- Cached credentials are correctly deserialized (including
expiration as a Date object)
Reproduction steps
- Configure an AWS profile with
role_arn + source_profile + mfa_serial
- Run
amplify env checkout <env-name> with CLI version 14.2.2 or later
- Observe the error
Resolved credential object is not valid — no MFA prompt appears
Log output
Resolved credential object is not valid
Additional information
This is a regression from PR #14315 (fixing #14290). The three bugs cascade — fixing Bug 1 alone surfaces Bug 2, and fixing Bug 2 alone surfaces Bug 3.
Affected file: packages/amplify-provider-awscloudformation/src/system-config-manager.ts
Fixes:
- Return
undefined from getCachedRoleCredentials() when no valid cached credentials exist
- Cache the flat credentials object (
roleCredentials.credentials) instead of the nested wrapper
- Convert
expiration from string to Date when returning cached credentials
How did you install the Amplify CLI?
npm
What version of Node.js are you using?
v24.11.1
What version of Amplify CLI are you using?
14.2.5 (regression introduced in v14.2.2 by PR #14315, still present as of 14.2.5)
What operating system are you using?
macOS
Did you make any manual changes to the cloud resources managed by Amplify? Please describe the changes if any.
No
Describe the bug
Three cascading bugs in the MFA role assumption credential caching logic were introduced by commit
04f7bcfc24(PR #14315, fixing #14290 "role assumption through profiles not working properly"). These bugs cause MFA-based role assumption to fail with the errorResolved credential object is not valid.Bug 1: MFA prompt never appears
getCachedRoleCredentials()always returns an object{ credentials: {} }even when no valid cached credentials exist. This causes the checkif (!roleCredentials)ingetRoleCredentials()to always be false, so the STSAssumeRolecall with MFA token is never executed.Bug 2: Credential cache validation always fails
Credentials are cached in nested format
{ credentials: { accessKeyId, ... } }butvalidateCachedCredentials()expects flat format{ accessKeyId, ... }. This causes cache validation to always fail, prompting for MFA on every CLI call.Bug 3:
identity.expiration.getTime is not a functionerrorWhen credentials are read from the JSON cache file, the
Dateobject forexpirationis deserialized as a string. The AWS SDK's@smithy/coremodule callsexpiration.getTime()which fails on a string.The fix in PR #14315 only addressed this in
getConfiguredAWSClientConfig(), butgetProfiledAwsConfig()is called directly duringamplify env checkoutwithout going through that code path.Expected behavior
expirationas aDateobject)Reproduction steps
role_arn+source_profile+mfa_serialamplify env checkout <env-name>with CLI version 14.2.2 or laterResolved credential object is not valid— no MFA prompt appearsLog output
Additional information
This is a regression from PR #14315 (fixing #14290). The three bugs cascade — fixing Bug 1 alone surfaces Bug 2, and fixing Bug 2 alone surfaces Bug 3.
Affected file:
packages/amplify-provider-awscloudformation/src/system-config-manager.tsFixes:
undefinedfromgetCachedRoleCredentials()when no valid cached credentials existroleCredentials.credentials) instead of the nested wrapperexpirationfrom string toDatewhen returning cached credentials