Repository navigation
Description
Describe the bug
MigrateLegacyCredentialStore is intended as a one-time migration of pre-Amplify (aws-sdk-ios) credentials, but it actually runs before the first credential-store operation of every process: the CredentialStoreState machine is in-memory and starts at .notConfigured on each launch, and Resolver.resolveNotConfigured maps both .migrateLegacyCredentialStore and .loadCredentialStore to the MigrateLegacyCredentialStore action.
The migration reads the aws-sdk-ios AWSCognitoCredentialsProvider keychain (service "<bundleId>.AWSCognitoCredentialsProvider.<identityPoolId>", keys accessKey/secretKey/sessionKey/expiration/identityId). If all five are present it unconditionally calls amplifyCredentialStore.saveCredential(...), overwriting whatever the Amplify store currently holds — there is no check that the Amplify store is empty (i.e. that this is actually a first-run migration). With no legacy user-pool tokens present, the signed-in userPoolAndIdentityPool blob is replaced by identityPoolOnly(legacyIdentityId, staleLegacyCredentials), silently destroying the signed-in session. The migration then wipes the legacy keychain (_removeAll()), but the coexisting SDK re-populates it on its next credential fetch, re-arming the problem for the following launch.
This breaks any app that legitimately uses aws-sdk-ios's AWSCognitoCredentialsProvider side by side with Amplify Auth — the standard pattern for AWSS3TransferUtility (background uploads, which aws-sdk-swift does not cover), with the provider's AWSIdentityProviderManager bridged to Amplify.Auth.fetchAuthSession() tokens. That provider persists its identity id and temp credentials in exactly the keychain the migration consumes, on every credential fetch.
Consequences we observed in production (amplify-swift 2.53.3 + aws-sdk-ios 2.41.0 AWSS3/AWSCore):
- Users are silently signed out on the cold start after any S3 upload (their user-pool tokens are erased by the overwrite).
- Worse, after an account switch the resurrected
identityPoolOnlyblob carries the previous account's identity id; presenting it yieldsNotAuthorizedException"Access to Identity … is forbidden" — and per Cached identity pool id is never evicted after "Access to Identity is forbidden" (NotAuthorizedException from GetCredentialsForIdentity) — session wedges permanently #4278 that error is never evicted, so the device wedges.
Issue #3225 appears to be an earlier symptom-level report of the same coexistence problem ("Getting logged out of Amplify when providing Credentials to [aws-sdk client] and restarting application").
Our app-side workaround is to call AWSCognitoCredentialsProvider.clearKeychain() before Amplify.configure() on every launch so the migration finds nothing — which works, but costs the legacy provider its credential cache and should not be necessary.
Steps To Reproduce
- App with Amplify Auth (user pool + identity pool), signed in.
- Also create an aws-sdk-ios
AWSCognitoCredentialsProviderfor the same identity pool (e.g. forAWSS3TransferUtility), with a customAWSIdentityProviderManagerreturning the Amplify session's id token, and perform any operation that makes it fetch credentials (an upload). Its keychain service<bundleId>.AWSCognitoCredentialsProvider.<poolId>now holds identityId + temp credentials. - Kill and relaunch the app; call
Amplify.Auth.fetchAuthSession().
Observed: MigrateLegacyCredentialStore runs, finds the "legacy" data written in step 2, and overwrites the signed-in Amplify credential blob with identityPoolOnly(identityId, staleCredentials). fetchAuthSession().isSignedIn is now false; the user is signed out. If the cached identity id belonged to a previously signed-in account, subsequent refreshes fail with "Access to Identity … is forbidden" instead.
Expected behavior
The migration should be a true one-time operation — e.g. guarded by a persisted "migration completed" marker, and/or skipped whenever the Amplify credential store already contains credentials. Data written by a coexisting aws-sdk-ios credentials provider must never overwrite an established Amplify session.
Amplify Framework Version
2.53.3
Amplify Categories
Auth
Dependency manager
Swift PM (amplify-swift); CocoaPods for aws-sdk-ios AWSS3/AWSCore 2.41.0
Xcode version
26
Relevant log output
Credential Store state change: CredentialStoreState.notConfigured -> migratingLegacyStore (every cold start)
After a launch following an S3 upload: fetchAuthSession().isSignedIn == false (user silently signed out)
or: AuthError: notAuthorized "Access to Identity 'us-east-1:…' is forbidden."Is this a regression?
No — the every-launch migrate-then-load flow is long-standing behavior of the credential store state machine.
Activity
cadivus commentedon Aug 31, 2026
Hi @garysmckiernan,
thanks for opening the issue! We are looking into it and get back to you.
harsh62 commentedon Sep 1, 2026
@garysmckiernan AWS SDK for iOS and Amplify Swift are not compatible with each other for Auth. We've never documented them to be used together in one single application. Even if we fix this issue, you could run into more issues later as we've not accounted for them to work together.
AWS SDK for Swift is a direct replacement of AWS SDK for IOS (which has now been deprecated). I would suggest to move migrate away from AWS SDK for iOS as solution for this problem.
MigrateLegacyCredentialStorehas been built to complete the migration once and throw away the SDK credentials.Please let me know if you have any questions or if you are running into issues while migrating to the Swift SDK.
garysmckiernan commentedon Sep 3, 2026
@harsh62 thanks for the response. I understand it's an odd mix but we took this approach as we want to use an accelerated endpoint for files over 5Mb.
My understanding is AWSS3StoragePlugin silently drops the accelerate flag for files over 5Mb so we implemented our own upload around TransferUtility and just use Amplify for Auth.
As suggested today I have looked at AWS SDK for Swift to create transfers via S3Client but then I lose background URLSession and have to DIY multipart.
Seems like no solution provides all the options I need (multipart, accelerated endpoint and background URLSession).
I am going to switch back to AWSS3StoragePlugin as slow upload is preferable to being logged out but please advise if you can think of an alternative.
harsh62 commentedon Sep 3, 2026
@garysmckiernan I think it would be best if you can create an issue/feature-request for the Storage plugin and we can tackle that. I can make sure your suggestion/issue is looked at on priority and we can improve the Storage plugin experience. When creating the issue, please provide examples,verbose logs and as much as details possible for the storage plugin.
If you already know what the solution is, please create a contribution PR and we will look at it.
Thanks
garysmckiernan commentedon Sep 4, 2026
Thanks @harsh62 will do. :)
github-actions commentedon Sep 4, 2026
This issue is now closed. Comments on closed issues are hard for our team to see.
If you need more assistance, please open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.