Skip to content

MigrateLegacyCredentialStore runs on every cold start and overwrites the Amplify session when the app also uses aws-sdk-ios's AWSCognitoCredentialsProvider #4279

Closed

Description

@garysmckiernan

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):

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

  1. App with Amplify Auth (user pool + identity pool), signed in.
  2. Also create an aws-sdk-ios AWSCognitoCredentialsProvider for the same identity pool (e.g. for AWSS3TransferUtility), with a custom AWSIdentityProviderManager returning 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.
  3. 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

  1. cadivus commented on Aug 31, 2026

    @cadivus
    Member

    Hi @garysmckiernan,
    thanks for opening the issue! We are looking into it and get back to you.

  2. added
    authIssues related to the Auth category
    storageIssues related to the Storage category
    bugSomething isn't working
    and removed on Aug 31, 2026
  3. harsh62 commented on Sep 1, 2026

    @harsh62
    Contributor

    @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.

    MigrateLegacyCredentialStore has 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.

  4. added
    questionGeneral question
    and removed
    bugSomething isn't working
    on Sep 1, 2026
  5. garysmckiernan commented on Sep 3, 2026

    @garysmckiernan
    Author

    @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.

  6. harsh62 commented on Sep 3, 2026

    @harsh62
    Contributor

    @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

  7. garysmckiernan commented on Sep 4, 2026

    @garysmckiernan
    Author

    Thanks @harsh62 will do. :)

  8. github-actions commented on Sep 4, 2026

    @github-actions
    Contributor

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    authIssues related to the Auth categoryquestionGeneral questionstorageIssues related to the Storage category

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions