From f00beb7dd982ae021caa9ae20fa1b3f6bf6cb37e Mon Sep 17 00:00:00 2001 From: ShrutiPundir17 Date: Sat, 16 May 2026 16:02:55 +0530 Subject: [PATCH 1/3] fix(aws-amplify): sync Cognito auth config and merge libraryOptions on reconfigure - Merge existing Amplify.libraryOptions when libraryOptions.Auth is provided so other categories are not dropped. - Call setAuthConfig on the default Cognito token provider when resourcesConfig.Auth changes on reconfigure (partial libraryOptions or config-only). - Merge prior libraryOptions on partial reconfigure without Auth override. - Add regression tests for the above behaviors. Co-authored-by: Cursor --- .../fix-init-singleton-auth-reconfigure.md | 5 + .../__tests__/initSingleton.test.ts | 95 +++++++++++++++++-- packages/aws-amplify/src/initSingleton.ts | 42 +++++++- 3 files changed, 128 insertions(+), 14 deletions(-) create mode 100644 .changeset/fix-init-singleton-auth-reconfigure.md diff --git a/.changeset/fix-init-singleton-auth-reconfigure.md b/.changeset/fix-init-singleton-auth-reconfigure.md new file mode 100644 index 00000000000..a1d8bd01b7d --- /dev/null +++ b/.changeset/fix-init-singleton-auth-reconfigure.md @@ -0,0 +1,5 @@ +--- +'aws-amplify': patch +--- + +fix(aws-amplify): merge libraryOptions when Auth is overridden and refresh default Cognito auth config on reconfigure. diff --git a/packages/aws-amplify/__tests__/initSingleton.test.ts b/packages/aws-amplify/__tests__/initSingleton.test.ts index 5d021b36743..c31ea32ab44 100644 --- a/packages/aws-amplify/__tests__/initSingleton.test.ts +++ b/packages/aws-amplify/__tests__/initSingleton.test.ts @@ -246,16 +246,29 @@ describe('initSingleton (DefaultAmplify)', () => { }); describe('when ResourcesConfig.Auth is defined', () => { - it('should just configure with the provided config and options when libraryOptions.Auth is defined', () => { + it('should merge with existing libraryOptions when libraryOptions.Auth is defined', () => { + const customTokenProvider = { getTokens: jest.fn() }; + const storageLibraryOptions = { + S3: { defaultAccessLevel: 'private' as const }, + }; + AmplifySingleton.libraryOptions = { + Storage: storageLibraryOptions, + }; const libraryOptions = { - Auth: { tokenProvider: { getTokens: jest.fn() } }, + Auth: { tokenProvider: customTokenProvider }, }; Amplify.configure(mockResourceConfig, libraryOptions); expect(mockAmplifySingletonConfigure).toHaveBeenCalledWith( mockResourceConfig, - libraryOptions, + { + Storage: storageLibraryOptions, + Auth: libraryOptions.Auth, + }, ); + expect( + mockCognitoUserPoolsTokenProviderSetAuthConfig, + ).not.toHaveBeenCalled(); }); describe('when the singleton libraryOptions have not yet been configured with Auth', () => { @@ -324,11 +337,12 @@ describe('initSingleton (DefaultAmplify)', () => { it('should preserve current auth providers (default or otherwise) and configure provider with a new CookieStorage instance', () => { const libraryOptions = { ssr: true }; + const authLibraryOptions = AmplifySingleton.libraryOptions.Auth; Amplify.configure(mockResourceConfig, libraryOptions); expect( mockCognitoUserPoolsTokenProviderSetAuthConfig, - ).not.toHaveBeenCalled(); + ).toHaveBeenCalledWith(mockResourceConfig.Auth); expect(MockCookieStorage).toHaveBeenCalledWith({ sameSite: 'lax' }); expect( mockCognitoUserPoolsTokenProviderSetKeyValueStorage, @@ -336,7 +350,7 @@ describe('initSingleton (DefaultAmplify)', () => { expect(mockAmplifySingletonConfigure).toHaveBeenCalledWith( mockResourceConfig, { - Auth: AmplifySingleton.libraryOptions.Auth, + Auth: authLibraryOptions, ...libraryOptions, }, ); @@ -344,18 +358,19 @@ describe('initSingleton (DefaultAmplify)', () => { it('should preserve current auth providers (default or otherwise) and configure provider with defaultStorage', () => { const libraryOptions = { ssr: false }; + const authLibraryOptions = AmplifySingleton.libraryOptions.Auth; Amplify.configure(mockResourceConfig, libraryOptions); expect( mockCognitoUserPoolsTokenProviderSetAuthConfig, - ).not.toHaveBeenCalled(); + ).toHaveBeenCalledWith(mockResourceConfig.Auth); expect( mockCognitoUserPoolsTokenProviderSetKeyValueStorage, ).toHaveBeenCalledWith(defaultStorage); expect(mockAmplifySingletonConfigure).toHaveBeenCalledWith( mockResourceConfig, { - Auth: AmplifySingleton.libraryOptions.Auth, + Auth: authLibraryOptions, ...libraryOptions, }, ); @@ -365,30 +380,90 @@ describe('initSingleton (DefaultAmplify)', () => { const libraryOptions = { Storage: { S3: { isObjectLockEnabled: true } }, }; + const authLibraryOptions = AmplifySingleton.libraryOptions.Auth; Amplify.configure(mockResourceConfig, libraryOptions); expect( mockCognitoUserPoolsTokenProviderSetAuthConfig, - ).not.toHaveBeenCalled(); + ).toHaveBeenCalledWith(mockResourceConfig.Auth); expect( mockCognitoUserPoolsTokenProviderSetKeyValueStorage, ).not.toHaveBeenCalled(); expect(mockAmplifySingletonConfigure).toHaveBeenCalledWith( mockResourceConfig, { - Auth: AmplifySingleton.libraryOptions.Auth, + Auth: authLibraryOptions, ...libraryOptions, }, ); }); - it('should just configure without touching libraryOptions', () => { + it('should preserve non-Auth library options when reconfiguring with partial libraryOptions', () => { + const storageLibraryOptions = { + S3: { defaultAccessLevel: 'private' as const }, + }; + AmplifySingleton.libraryOptions = { + Auth: { + tokenProvider: cognitoUserPoolsTokenProvider, + credentialsProvider: cognitoCredentialsProvider, + }, + Storage: storageLibraryOptions, + }; + const authLibraryOptions = AmplifySingleton.libraryOptions.Auth; + + Amplify.configure(mockResourceConfig, { ssr: true }); + + expect( + mockCognitoUserPoolsTokenProviderSetAuthConfig, + ).toHaveBeenCalledWith(mockResourceConfig.Auth); + expect(mockAmplifySingletonConfigure).toHaveBeenCalledWith( + mockResourceConfig, + { + Auth: authLibraryOptions, + Storage: storageLibraryOptions, + ssr: true, + }, + ); + }); + + it('should sync default Cognito auth config when reconfiguring with resource config only', () => { Amplify.configure(mockResourceConfig); + expect( + mockCognitoUserPoolsTokenProviderSetAuthConfig, + ).toHaveBeenCalledWith(mockResourceConfig.Auth); expect(mockAmplifySingletonConfigure).toHaveBeenCalledWith( mockResourceConfig, ); }); + + it('should sync default Cognito auth config when libraryOptions.Auth overrides with default provider', () => { + const updatedResourceConfig: ResourcesConfig = { + Auth: { + Cognito: { + userPoolClientId: 'newClientId', + userPoolId: 'newPoolId', + }, + }, + }; + AmplifySingleton.libraryOptions = { + Auth: { + tokenProvider: cognitoUserPoolsTokenProvider, + credentialsProvider: cognitoCredentialsProvider, + }, + }; + + Amplify.configure(updatedResourceConfig, { + Auth: { + tokenProvider: cognitoUserPoolsTokenProvider, + credentialsProvider: cognitoCredentialsProvider, + }, + }); + + expect( + mockCognitoUserPoolsTokenProviderSetAuthConfig, + ).toHaveBeenCalledWith(updatedResourceConfig.Auth); + }); }); it('should invoke AmplifySingleton.configure with other provided library options', () => { diff --git a/packages/aws-amplify/src/initSingleton.ts b/packages/aws-amplify/src/initSingleton.ts index 6168cc25b51..fa77d668955 100644 --- a/packages/aws-amplify/src/initSingleton.ts +++ b/packages/aws-amplify/src/initSingleton.ts @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { Amplify, + AuthConfig, CookieStorage, LibraryOptions, ResourcesConfig, @@ -20,6 +21,15 @@ import { cognitoUserPoolsTokenProvider, } from './auth/cognito'; +const usesDefaultCognitoTokenProvider = ( + authLibraryOptions?: LibraryOptions['Auth'], +): boolean => + authLibraryOptions?.tokenProvider === cognitoUserPoolsTokenProvider; + +const syncDefaultCognitoAuthConfig = (authConfig: AuthConfig): void => { + cognitoUserPoolsTokenProvider.setAuthConfig(authConfig); +}; + export const DefaultAmplify = { /** * Configures Amplify with the {@link resourceConfig} and {@link libraryOptions}. @@ -56,10 +66,25 @@ export const DefaultAmplify = { return; } - // If Auth options are provided, always just configure as is. - // Otherwise, we can assume no Auth libraryOptions were provided from here on. + // If Auth options are provided, merge with existing libraryOptions so other categories are preserved. if (libraryOptions?.Auth) { - Amplify.configure(resolvedResourceConfig, libraryOptions); + const mergedLibraryOptions: LibraryOptions = { + ...Amplify.libraryOptions, + ...libraryOptions, + }; + + if (usesDefaultCognitoTokenProvider(mergedLibraryOptions.Auth)) { + syncDefaultCognitoAuthConfig(resolvedResourceConfig.Auth); + + if (libraryOptions.ssr !== undefined) { + cognitoUserPoolsTokenProvider.setKeyValueStorage( + // TODO: allow configure with a public interface + resolvedKeyValueStorage, + ); + } + } + + Amplify.configure(resolvedResourceConfig, mergedLibraryOptions); return; } @@ -97,9 +122,14 @@ export const DefaultAmplify = { authLibraryOptions.credentialsProvider = resolvedCredentialsProvider; } + if (usesDefaultCognitoTokenProvider(authLibraryOptions)) { + syncDefaultCognitoAuthConfig(resolvedResourceConfig.Auth); + } + Amplify.configure(resolvedResourceConfig, { - Auth: authLibraryOptions, + ...Amplify.libraryOptions, ...libraryOptions, + Auth: authLibraryOptions, }); return; @@ -107,6 +137,10 @@ export const DefaultAmplify = { // Finally, if there were no libraryOptions given at all, we should simply not touch the currently // configured libraryOptions. + if (usesDefaultCognitoTokenProvider(Amplify.libraryOptions.Auth)) { + syncDefaultCognitoAuthConfig(resolvedResourceConfig.Auth); + } + Amplify.configure(resolvedResourceConfig); }, /** From f67c6517280618d477aa3e99398100f3ac1782e1 Mon Sep 17 00:00:00 2001 From: ShrutiPundir17 Date: Sat, 16 May 2026 16:30:20 +0530 Subject: [PATCH 2/3] test(aws-amplify): add DefaultAmplify integration tests with real core singleton Validates Storage preservation and setAuthConfig on reconfigure without mocking @aws-amplify/core. Co-authored-by: Cursor --- .../initSingleton.integration.test.ts | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 packages/aws-amplify/__tests__/initSingleton.integration.test.ts diff --git a/packages/aws-amplify/__tests__/initSingleton.integration.test.ts b/packages/aws-amplify/__tests__/initSingleton.integration.test.ts new file mode 100644 index 00000000000..df87b946ec7 --- /dev/null +++ b/packages/aws-amplify/__tests__/initSingleton.integration.test.ts @@ -0,0 +1,123 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +/** + * Integration-style tests using the real @aws-amplify/core Amplify singleton + * (initSingleton.test.ts mocks core). + */ +import { Amplify as CoreAmplify, ResourcesConfig } from '@aws-amplify/core'; + +import { cognitoUserPoolsTokenProvider } from '../src/auth/cognito'; +import { Amplify as DefaultAmplify } from '../src'; + +const poolAConfig: ResourcesConfig = { + Auth: { + Cognito: { + userPoolClientId: 'client-a', + userPoolId: 'pool-a', + }, + }, +}; + +const poolBConfig: ResourcesConfig = { + Auth: { + Cognito: { + userPoolClientId: 'client-b', + userPoolId: 'pool-b', + }, + }, +}; + +const storageLibraryOptions = { + Storage: { + S3: { + defaultAccessLevel: 'private' as const, + isObjectLockEnabled: true, + }, + }, +}; + +describe('DefaultAmplify.configure integration', () => { + let setAuthConfigSpy: jest.SpyInstance; + let setKeyValueStorageSpy: jest.SpyInstance; + + beforeEach(() => { + CoreAmplify.libraryOptions = {}; + CoreAmplify.resourcesConfig = {}; + setAuthConfigSpy = jest.spyOn( + cognitoUserPoolsTokenProvider, + 'setAuthConfig', + ); + setKeyValueStorageSpy = jest.spyOn( + cognitoUserPoolsTokenProvider, + 'setKeyValueStorage', + ); + }); + + afterEach(() => { + setAuthConfigSpy.mockRestore(); + setKeyValueStorageSpy.mockRestore(); + CoreAmplify.libraryOptions = {}; + CoreAmplify.resourcesConfig = {}; + }); + + it('keeps Storage and refreshes Cognito auth config on partial reconfigure', () => { + DefaultAmplify.configure(poolAConfig, storageLibraryOptions); + + expect(CoreAmplify.libraryOptions.Storage).toEqual( + storageLibraryOptions.Storage, + ); + expect(CoreAmplify.libraryOptions.Auth?.tokenProvider).toBe( + cognitoUserPoolsTokenProvider, + ); + expect(setAuthConfigSpy).toHaveBeenCalledWith(poolAConfig.Auth); + + setAuthConfigSpy.mockClear(); + + DefaultAmplify.configure(poolBConfig, { ssr: false }); + + expect(CoreAmplify.libraryOptions.Storage).toEqual( + storageLibraryOptions.Storage, + ); + expect(CoreAmplify.getConfig().Auth?.Cognito?.userPoolClientId).toBe( + 'client-b', + ); + expect(setAuthConfigSpy).toHaveBeenCalledWith(poolBConfig.Auth); + }); + + it('merges prior libraryOptions when libraryOptions.Auth overrides default provider', () => { + DefaultAmplify.configure(poolAConfig, storageLibraryOptions); + + setAuthConfigSpy.mockClear(); + + DefaultAmplify.configure(poolBConfig, { + Auth: { + tokenProvider: cognitoUserPoolsTokenProvider, + credentialsProvider: + CoreAmplify.libraryOptions.Auth!.credentialsProvider!, + }, + }); + + expect(CoreAmplify.libraryOptions.Storage).toEqual( + storageLibraryOptions.Storage, + ); + expect(setAuthConfigSpy).toHaveBeenCalledWith(poolBConfig.Auth); + expect(CoreAmplify.getConfig().Auth?.Cognito?.userPoolClientId).toBe( + 'client-b', + ); + }); + + it('syncs default Cognito auth config when only resource config is passed', () => { + DefaultAmplify.configure(poolAConfig, storageLibraryOptions); + + setAuthConfigSpy.mockClear(); + + DefaultAmplify.configure(poolBConfig); + + expect(CoreAmplify.libraryOptions.Storage).toEqual( + storageLibraryOptions.Storage, + ); + expect(setAuthConfigSpy).toHaveBeenCalledWith(poolBConfig.Auth); + expect(CoreAmplify.getConfig().Auth?.Cognito?.userPoolId).toBe('pool-b'); + }); +}); From 5bee227203883f3862e1ce5ed9d185f20f152873 Mon Sep 17 00:00:00 2001 From: ShrutiPundir17 Date: Wed, 3 Jun 2026 17:48:32 +0530 Subject: [PATCH 3/3] fix(aws-amplify): refresh default Cognito auth config on reconfigure Simplify initSingleton per maintainer feedback: pass-through when libraryOptions.Auth is set; otherwise always setAuthConfig and SSR-aware setKeyValueStorage. Removes libraryOptions merge from this PR. Co-authored-by: Cursor --- .../fix-init-singleton-auth-reconfigure.md | 2 +- .../initSingleton.integration.test.ts | 44 ++------ .../__tests__/initSingleton.test.ts | 94 ++++++---------- packages/aws-amplify/src/initSingleton.ts | 103 +++--------------- 4 files changed, 63 insertions(+), 180 deletions(-) diff --git a/.changeset/fix-init-singleton-auth-reconfigure.md b/.changeset/fix-init-singleton-auth-reconfigure.md index a1d8bd01b7d..e164a8b8ce0 100644 --- a/.changeset/fix-init-singleton-auth-reconfigure.md +++ b/.changeset/fix-init-singleton-auth-reconfigure.md @@ -2,4 +2,4 @@ 'aws-amplify': patch --- -fix(aws-amplify): merge libraryOptions when Auth is overridden and refresh default Cognito auth config on reconfigure. +fix(aws-amplify): refresh default Cognito auth config on DefaultAmplify reconfigure. diff --git a/packages/aws-amplify/__tests__/initSingleton.integration.test.ts b/packages/aws-amplify/__tests__/initSingleton.integration.test.ts index df87b946ec7..46352c48395 100644 --- a/packages/aws-amplify/__tests__/initSingleton.integration.test.ts +++ b/packages/aws-amplify/__tests__/initSingleton.integration.test.ts @@ -28,15 +28,6 @@ const poolBConfig: ResourcesConfig = { }, }; -const storageLibraryOptions = { - Storage: { - S3: { - defaultAccessLevel: 'private' as const, - isObjectLockEnabled: true, - }, - }, -}; - describe('DefaultAmplify.configure integration', () => { let setAuthConfigSpy: jest.SpyInstance; let setKeyValueStorageSpy: jest.SpyInstance; @@ -61,32 +52,25 @@ describe('DefaultAmplify.configure integration', () => { CoreAmplify.resourcesConfig = {}; }); - it('keeps Storage and refreshes Cognito auth config on partial reconfigure', () => { - DefaultAmplify.configure(poolAConfig, storageLibraryOptions); + it('refreshes Cognito auth config on reconfigure with partial libraryOptions', () => { + DefaultAmplify.configure(poolAConfig); - expect(CoreAmplify.libraryOptions.Storage).toEqual( - storageLibraryOptions.Storage, - ); - expect(CoreAmplify.libraryOptions.Auth?.tokenProvider).toBe( - cognitoUserPoolsTokenProvider, - ); expect(setAuthConfigSpy).toHaveBeenCalledWith(poolAConfig.Auth); setAuthConfigSpy.mockClear(); + setKeyValueStorageSpy.mockClear(); DefaultAmplify.configure(poolBConfig, { ssr: false }); - expect(CoreAmplify.libraryOptions.Storage).toEqual( - storageLibraryOptions.Storage, - ); + expect(setAuthConfigSpy).toHaveBeenCalledWith(poolBConfig.Auth); + expect(setKeyValueStorageSpy).toHaveBeenCalled(); expect(CoreAmplify.getConfig().Auth?.Cognito?.userPoolClientId).toBe( 'client-b', ); - expect(setAuthConfigSpy).toHaveBeenCalledWith(poolBConfig.Auth); }); - it('merges prior libraryOptions when libraryOptions.Auth overrides default provider', () => { - DefaultAmplify.configure(poolAConfig, storageLibraryOptions); + it('passes through when libraryOptions.Auth is provided', () => { + DefaultAmplify.configure(poolAConfig); setAuthConfigSpy.mockClear(); @@ -98,26 +82,22 @@ describe('DefaultAmplify.configure integration', () => { }, }); - expect(CoreAmplify.libraryOptions.Storage).toEqual( - storageLibraryOptions.Storage, - ); - expect(setAuthConfigSpy).toHaveBeenCalledWith(poolBConfig.Auth); + expect(setAuthConfigSpy).not.toHaveBeenCalled(); expect(CoreAmplify.getConfig().Auth?.Cognito?.userPoolClientId).toBe( 'client-b', ); }); - it('syncs default Cognito auth config when only resource config is passed', () => { - DefaultAmplify.configure(poolAConfig, storageLibraryOptions); + it('refreshes Cognito auth config when only resource config is passed', () => { + DefaultAmplify.configure(poolAConfig); setAuthConfigSpy.mockClear(); + setKeyValueStorageSpy.mockClear(); DefaultAmplify.configure(poolBConfig); - expect(CoreAmplify.libraryOptions.Storage).toEqual( - storageLibraryOptions.Storage, - ); expect(setAuthConfigSpy).toHaveBeenCalledWith(poolBConfig.Auth); + expect(setKeyValueStorageSpy).toHaveBeenCalled(); expect(CoreAmplify.getConfig().Auth?.Cognito?.userPoolId).toBe('pool-b'); }); }); diff --git a/packages/aws-amplify/__tests__/initSingleton.test.ts b/packages/aws-amplify/__tests__/initSingleton.test.ts index c31ea32ab44..0e6ad875a50 100644 --- a/packages/aws-amplify/__tests__/initSingleton.test.ts +++ b/packages/aws-amplify/__tests__/initSingleton.test.ts @@ -246,14 +246,8 @@ describe('initSingleton (DefaultAmplify)', () => { }); describe('when ResourcesConfig.Auth is defined', () => { - it('should merge with existing libraryOptions when libraryOptions.Auth is defined', () => { + it('should pass through when libraryOptions.Auth is defined', () => { const customTokenProvider = { getTokens: jest.fn() }; - const storageLibraryOptions = { - S3: { defaultAccessLevel: 'private' as const }, - }; - AmplifySingleton.libraryOptions = { - Storage: storageLibraryOptions, - }; const libraryOptions = { Auth: { tokenProvider: customTokenProvider }, }; @@ -261,10 +255,7 @@ describe('initSingleton (DefaultAmplify)', () => { expect(mockAmplifySingletonConfigure).toHaveBeenCalledWith( mockResourceConfig, - { - Storage: storageLibraryOptions, - Auth: libraryOptions.Auth, - }, + libraryOptions, ); expect( mockCognitoUserPoolsTokenProviderSetAuthConfig, @@ -335,9 +326,8 @@ describe('initSingleton (DefaultAmplify)', () => { }; }); - it('should preserve current auth providers (default or otherwise) and configure provider with a new CookieStorage instance', () => { + it('should refresh default Cognito auth config and configure provider with a new CookieStorage instance on reconfigure', () => { const libraryOptions = { ssr: true }; - const authLibraryOptions = AmplifySingleton.libraryOptions.Auth; Amplify.configure(mockResourceConfig, libraryOptions); expect( @@ -350,15 +340,18 @@ describe('initSingleton (DefaultAmplify)', () => { expect(mockAmplifySingletonConfigure).toHaveBeenCalledWith( mockResourceConfig, { - Auth: authLibraryOptions, ...libraryOptions, + Auth: { + tokenProvider: cognitoUserPoolsTokenProvider, + credentialsProvider: + mockCognitoAWSCredentialsAndIdentityIdProviderInstance, + }, }, ); }); - it('should preserve current auth providers (default or otherwise) and configure provider with defaultStorage', () => { + it('should refresh default Cognito auth config and configure provider with defaultStorage on reconfigure', () => { const libraryOptions = { ssr: false }; - const authLibraryOptions = AmplifySingleton.libraryOptions.Auth; Amplify.configure(mockResourceConfig, libraryOptions); expect( @@ -370,17 +363,19 @@ describe('initSingleton (DefaultAmplify)', () => { expect(mockAmplifySingletonConfigure).toHaveBeenCalledWith( mockResourceConfig, { - Auth: authLibraryOptions, ...libraryOptions, + Auth: { + tokenProvider: cognitoUserPoolsTokenProvider, + credentialsProvider: cognitoCredentialsProvider, + }, }, ); }); - it('should preserve current auth providers (default or otherwise)', () => { + it('should refresh default Cognito auth config when reconfiguring with non-Auth libraryOptions', () => { const libraryOptions = { Storage: { S3: { isObjectLockEnabled: true } }, }; - const authLibraryOptions = AmplifySingleton.libraryOptions.Auth; Amplify.configure(mockResourceConfig, libraryOptions); expect( @@ -388,56 +383,40 @@ describe('initSingleton (DefaultAmplify)', () => { ).toHaveBeenCalledWith(mockResourceConfig.Auth); expect( mockCognitoUserPoolsTokenProviderSetKeyValueStorage, - ).not.toHaveBeenCalled(); + ).toHaveBeenCalledWith(defaultStorage); expect(mockAmplifySingletonConfigure).toHaveBeenCalledWith( mockResourceConfig, { - Auth: authLibraryOptions, ...libraryOptions, + Auth: { + tokenProvider: cognitoUserPoolsTokenProvider, + credentialsProvider: cognitoCredentialsProvider, + }, }, ); }); - it('should preserve non-Auth library options when reconfiguring with partial libraryOptions', () => { - const storageLibraryOptions = { - S3: { defaultAccessLevel: 'private' as const }, - }; - AmplifySingleton.libraryOptions = { - Auth: { - tokenProvider: cognitoUserPoolsTokenProvider, - credentialsProvider: cognitoCredentialsProvider, - }, - Storage: storageLibraryOptions, - }; - const authLibraryOptions = AmplifySingleton.libraryOptions.Auth; - - Amplify.configure(mockResourceConfig, { ssr: true }); + it('should refresh default Cognito auth config when reconfiguring with resource config only', () => { + Amplify.configure(mockResourceConfig); expect( mockCognitoUserPoolsTokenProviderSetAuthConfig, ).toHaveBeenCalledWith(mockResourceConfig.Auth); + expect( + mockCognitoUserPoolsTokenProviderSetKeyValueStorage, + ).toHaveBeenCalledWith(defaultStorage); expect(mockAmplifySingletonConfigure).toHaveBeenCalledWith( mockResourceConfig, { - Auth: authLibraryOptions, - Storage: storageLibraryOptions, - ssr: true, + Auth: { + tokenProvider: cognitoUserPoolsTokenProvider, + credentialsProvider: cognitoCredentialsProvider, + }, }, ); }); - it('should sync default Cognito auth config when reconfiguring with resource config only', () => { - Amplify.configure(mockResourceConfig); - - expect( - mockCognitoUserPoolsTokenProviderSetAuthConfig, - ).toHaveBeenCalledWith(mockResourceConfig.Auth); - expect(mockAmplifySingletonConfigure).toHaveBeenCalledWith( - mockResourceConfig, - ); - }); - - it('should sync default Cognito auth config when libraryOptions.Auth overrides with default provider', () => { + it('should pass through when libraryOptions.Auth is provided on reconfigure', () => { const updatedResourceConfig: ResourcesConfig = { Auth: { Cognito: { @@ -446,23 +425,22 @@ describe('initSingleton (DefaultAmplify)', () => { }, }, }; - AmplifySingleton.libraryOptions = { + const libraryOptions = { Auth: { tokenProvider: cognitoUserPoolsTokenProvider, credentialsProvider: cognitoCredentialsProvider, }, }; - Amplify.configure(updatedResourceConfig, { - Auth: { - tokenProvider: cognitoUserPoolsTokenProvider, - credentialsProvider: cognitoCredentialsProvider, - }, - }); + Amplify.configure(updatedResourceConfig, libraryOptions); expect( mockCognitoUserPoolsTokenProviderSetAuthConfig, - ).toHaveBeenCalledWith(updatedResourceConfig.Auth); + ).not.toHaveBeenCalled(); + expect(mockAmplifySingletonConfigure).toHaveBeenCalledWith( + updatedResourceConfig, + libraryOptions, + ); }); }); diff --git a/packages/aws-amplify/src/initSingleton.ts b/packages/aws-amplify/src/initSingleton.ts index fa77d668955..bfcc9960610 100644 --- a/packages/aws-amplify/src/initSingleton.ts +++ b/packages/aws-amplify/src/initSingleton.ts @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 import { Amplify, - AuthConfig, CookieStorage, LibraryOptions, ResourcesConfig, @@ -21,15 +20,6 @@ import { cognitoUserPoolsTokenProvider, } from './auth/cognito'; -const usesDefaultCognitoTokenProvider = ( - authLibraryOptions?: LibraryOptions['Auth'], -): boolean => - authLibraryOptions?.tokenProvider === cognitoUserPoolsTokenProvider; - -const syncDefaultCognitoAuthConfig = (authConfig: AuthConfig): void => { - cognitoUserPoolsTokenProvider.setAuthConfig(authConfig); -}; - export const DefaultAmplify = { /** * Configures Amplify with the {@link resourceConfig} and {@link libraryOptions}. @@ -58,90 +48,25 @@ export const DefaultAmplify = { ) : cognitoCredentialsProvider; - // If no Auth config is provided, no special handling will be required, configure as is. - // Otherwise, we can assume an Auth config is provided from here on. - if (!resolvedResourceConfig.Auth) { + if (!resolvedResourceConfig.Auth || libraryOptions?.Auth) { Amplify.configure(resolvedResourceConfig, libraryOptions); return; } - // If Auth options are provided, merge with existing libraryOptions so other categories are preserved. - if (libraryOptions?.Auth) { - const mergedLibraryOptions: LibraryOptions = { - ...Amplify.libraryOptions, - ...libraryOptions, - }; - - if (usesDefaultCognitoTokenProvider(mergedLibraryOptions.Auth)) { - syncDefaultCognitoAuthConfig(resolvedResourceConfig.Auth); - - if (libraryOptions.ssr !== undefined) { - cognitoUserPoolsTokenProvider.setKeyValueStorage( - // TODO: allow configure with a public interface - resolvedKeyValueStorage, - ); - } - } - - Amplify.configure(resolvedResourceConfig, mergedLibraryOptions); - - return; - } - - // If no Auth libraryOptions were previously configured, then always add default providers. - if (!Amplify.libraryOptions.Auth) { - cognitoUserPoolsTokenProvider.setAuthConfig(resolvedResourceConfig.Auth); - cognitoUserPoolsTokenProvider.setKeyValueStorage( - // TODO: allow configure with a public interface - resolvedKeyValueStorage, - ); - - Amplify.configure(resolvedResourceConfig, { - ...libraryOptions, - Auth: { - tokenProvider: cognitoUserPoolsTokenProvider, - credentialsProvider: resolvedCredentialsProvider, - }, - }); - - return; - } - - // At this point, Auth libraryOptions would have been previously configured and no overriding - // Auth options were given, so we should preserve the currently configured Auth libraryOptions. - if (libraryOptions) { - const authLibraryOptions = Amplify.libraryOptions.Auth; - // If ssr is provided through libraryOptions, we should respect the intentional reconfiguration. - if (libraryOptions.ssr !== undefined) { - cognitoUserPoolsTokenProvider.setKeyValueStorage( - // TODO: allow configure with a public interface - resolvedKeyValueStorage, - ); - - authLibraryOptions.credentialsProvider = resolvedCredentialsProvider; - } - - if (usesDefaultCognitoTokenProvider(authLibraryOptions)) { - syncDefaultCognitoAuthConfig(resolvedResourceConfig.Auth); - } - - Amplify.configure(resolvedResourceConfig, { - ...Amplify.libraryOptions, - ...libraryOptions, - Auth: authLibraryOptions, - }); - - return; - } - - // Finally, if there were no libraryOptions given at all, we should simply not touch the currently - // configured libraryOptions. - if (usesDefaultCognitoTokenProvider(Amplify.libraryOptions.Auth)) { - syncDefaultCognitoAuthConfig(resolvedResourceConfig.Auth); - } - - Amplify.configure(resolvedResourceConfig); + cognitoUserPoolsTokenProvider.setAuthConfig(resolvedResourceConfig.Auth); + cognitoUserPoolsTokenProvider.setKeyValueStorage( + // TODO: allow configure with a public interface + resolvedKeyValueStorage, + ); + + Amplify.configure(resolvedResourceConfig, { + ...libraryOptions, + Auth: { + tokenProvider: cognitoUserPoolsTokenProvider, + credentialsProvider: resolvedCredentialsProvider, + }, + }); }, /** * Returns the {@link ResourcesConfig} object passed in as the `resourceConfig` parameter when calling