Skip to content

Commit 6f5a076

Browse files
fix(aws-amplify): sync Cognito auth config on reconfigure (#14819)
* 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 <cursoragent@cursor.com> * fix(aws-amplify): refresh default Cognito auth config on reconfigure pass-through when libraryOptions.Auth is set; otherwise always setAuthConfig and SSR-aware setKeyValueStorage. --------- Co-authored-by: ShrutiPundir17 <ShrutiPundir17@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 00713e1 commit 6f5a076

4 files changed

Lines changed: 187 additions & 67 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'aws-amplify': patch
3+
---
4+
5+
fix(aws-amplify): refresh default Cognito auth config on DefaultAmplify reconfigure.
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
/**
5+
* Integration-style tests using the real @aws-amplify/core Amplify singleton
6+
* (initSingleton.test.ts mocks core).
7+
*/
8+
import { Amplify as CoreAmplify, ResourcesConfig } from '@aws-amplify/core';
9+
10+
import { cognitoUserPoolsTokenProvider } from '../src/auth/cognito';
11+
import { Amplify as DefaultAmplify } from '../src';
12+
13+
const poolAConfig: ResourcesConfig = {
14+
Auth: {
15+
Cognito: {
16+
userPoolClientId: 'client-a',
17+
userPoolId: 'pool-a',
18+
},
19+
},
20+
};
21+
22+
const poolBConfig: ResourcesConfig = {
23+
Auth: {
24+
Cognito: {
25+
userPoolClientId: 'client-b',
26+
userPoolId: 'pool-b',
27+
},
28+
},
29+
};
30+
31+
describe('DefaultAmplify.configure integration', () => {
32+
let setAuthConfigSpy: jest.SpyInstance;
33+
let setKeyValueStorageSpy: jest.SpyInstance;
34+
35+
beforeEach(() => {
36+
CoreAmplify.libraryOptions = {};
37+
CoreAmplify.resourcesConfig = {};
38+
setAuthConfigSpy = jest.spyOn(
39+
cognitoUserPoolsTokenProvider,
40+
'setAuthConfig',
41+
);
42+
setKeyValueStorageSpy = jest.spyOn(
43+
cognitoUserPoolsTokenProvider,
44+
'setKeyValueStorage',
45+
);
46+
});
47+
48+
afterEach(() => {
49+
setAuthConfigSpy.mockRestore();
50+
setKeyValueStorageSpy.mockRestore();
51+
CoreAmplify.libraryOptions = {};
52+
CoreAmplify.resourcesConfig = {};
53+
});
54+
55+
it('refreshes Cognito auth config on reconfigure with partial libraryOptions', () => {
56+
DefaultAmplify.configure(poolAConfig);
57+
58+
expect(setAuthConfigSpy).toHaveBeenCalledWith(poolAConfig.Auth);
59+
60+
setAuthConfigSpy.mockClear();
61+
setKeyValueStorageSpy.mockClear();
62+
63+
DefaultAmplify.configure(poolBConfig, { ssr: false });
64+
65+
expect(setAuthConfigSpy).toHaveBeenCalledWith(poolBConfig.Auth);
66+
expect(setKeyValueStorageSpy).toHaveBeenCalled();
67+
expect(CoreAmplify.getConfig().Auth?.Cognito?.userPoolClientId).toBe(
68+
'client-b',
69+
);
70+
});
71+
72+
it('passes through when libraryOptions.Auth is provided', () => {
73+
DefaultAmplify.configure(poolAConfig);
74+
75+
setAuthConfigSpy.mockClear();
76+
77+
DefaultAmplify.configure(poolBConfig, {
78+
Auth: {
79+
tokenProvider: cognitoUserPoolsTokenProvider,
80+
credentialsProvider:
81+
CoreAmplify.libraryOptions.Auth!.credentialsProvider!,
82+
},
83+
});
84+
85+
expect(setAuthConfigSpy).not.toHaveBeenCalled();
86+
expect(CoreAmplify.getConfig().Auth?.Cognito?.userPoolClientId).toBe(
87+
'client-b',
88+
);
89+
});
90+
91+
it('refreshes Cognito auth config when only resource config is passed', () => {
92+
DefaultAmplify.configure(poolAConfig);
93+
94+
setAuthConfigSpy.mockClear();
95+
setKeyValueStorageSpy.mockClear();
96+
97+
DefaultAmplify.configure(poolBConfig);
98+
99+
expect(setAuthConfigSpy).toHaveBeenCalledWith(poolBConfig.Auth);
100+
expect(setKeyValueStorageSpy).toHaveBeenCalled();
101+
expect(CoreAmplify.getConfig().Auth?.Cognito?.userPoolId).toBe('pool-b');
102+
});
103+
});

packages/aws-amplify/__tests__/initSingleton.test.ts

Lines changed: 66 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -246,16 +246,20 @@ describe('initSingleton (DefaultAmplify)', () => {
246246
});
247247

248248
describe('when ResourcesConfig.Auth is defined', () => {
249-
it('should just configure with the provided config and options when libraryOptions.Auth is defined', () => {
249+
it('should pass through when libraryOptions.Auth is defined', () => {
250+
const customTokenProvider = { getTokens: jest.fn() };
250251
const libraryOptions = {
251-
Auth: { tokenProvider: { getTokens: jest.fn() } },
252+
Auth: { tokenProvider: customTokenProvider },
252253
};
253254
Amplify.configure(mockResourceConfig, libraryOptions);
254255

255256
expect(mockAmplifySingletonConfigure).toHaveBeenCalledWith(
256257
mockResourceConfig,
257258
libraryOptions,
258259
);
260+
expect(
261+
mockCognitoUserPoolsTokenProviderSetAuthConfig,
262+
).not.toHaveBeenCalled();
259263
});
260264

261265
describe('when the singleton libraryOptions have not yet been configured with Auth', () => {
@@ -322,71 +326,120 @@ describe('initSingleton (DefaultAmplify)', () => {
322326
};
323327
});
324328

325-
it('should preserve current auth providers (default or otherwise) and configure provider with a new CookieStorage instance', () => {
329+
it('should refresh default Cognito auth config and configure provider with a new CookieStorage instance on reconfigure', () => {
326330
const libraryOptions = { ssr: true };
327331
Amplify.configure(mockResourceConfig, libraryOptions);
328332

329333
expect(
330334
mockCognitoUserPoolsTokenProviderSetAuthConfig,
331-
).not.toHaveBeenCalled();
335+
).toHaveBeenCalledWith(mockResourceConfig.Auth);
332336
expect(MockCookieStorage).toHaveBeenCalledWith({ sameSite: 'lax' });
333337
expect(
334338
mockCognitoUserPoolsTokenProviderSetKeyValueStorage,
335339
).toHaveBeenCalledWith(mockCookieStorageInstance);
336340
expect(mockAmplifySingletonConfigure).toHaveBeenCalledWith(
337341
mockResourceConfig,
338342
{
339-
Auth: AmplifySingleton.libraryOptions.Auth,
340343
...libraryOptions,
344+
Auth: {
345+
tokenProvider: cognitoUserPoolsTokenProvider,
346+
credentialsProvider:
347+
mockCognitoAWSCredentialsAndIdentityIdProviderInstance,
348+
},
341349
},
342350
);
343351
});
344352

345-
it('should preserve current auth providers (default or otherwise) and configure provider with defaultStorage', () => {
353+
it('should refresh default Cognito auth config and configure provider with defaultStorage on reconfigure', () => {
346354
const libraryOptions = { ssr: false };
347355
Amplify.configure(mockResourceConfig, libraryOptions);
348356

349357
expect(
350358
mockCognitoUserPoolsTokenProviderSetAuthConfig,
351-
).not.toHaveBeenCalled();
359+
).toHaveBeenCalledWith(mockResourceConfig.Auth);
352360
expect(
353361
mockCognitoUserPoolsTokenProviderSetKeyValueStorage,
354362
).toHaveBeenCalledWith(defaultStorage);
355363
expect(mockAmplifySingletonConfigure).toHaveBeenCalledWith(
356364
mockResourceConfig,
357365
{
358-
Auth: AmplifySingleton.libraryOptions.Auth,
359366
...libraryOptions,
367+
Auth: {
368+
tokenProvider: cognitoUserPoolsTokenProvider,
369+
credentialsProvider: cognitoCredentialsProvider,
370+
},
360371
},
361372
);
362373
});
363374

364-
it('should preserve current auth providers (default or otherwise)', () => {
375+
it('should refresh default Cognito auth config when reconfiguring with non-Auth libraryOptions', () => {
365376
const libraryOptions = {
366377
Storage: { S3: { isObjectLockEnabled: true } },
367378
};
368379
Amplify.configure(mockResourceConfig, libraryOptions);
369380

370381
expect(
371382
mockCognitoUserPoolsTokenProviderSetAuthConfig,
372-
).not.toHaveBeenCalled();
383+
).toHaveBeenCalledWith(mockResourceConfig.Auth);
373384
expect(
374385
mockCognitoUserPoolsTokenProviderSetKeyValueStorage,
375-
).not.toHaveBeenCalled();
386+
).toHaveBeenCalledWith(defaultStorage);
376387
expect(mockAmplifySingletonConfigure).toHaveBeenCalledWith(
377388
mockResourceConfig,
378389
{
379-
Auth: AmplifySingleton.libraryOptions.Auth,
380390
...libraryOptions,
391+
Auth: {
392+
tokenProvider: cognitoUserPoolsTokenProvider,
393+
credentialsProvider: cognitoCredentialsProvider,
394+
},
381395
},
382396
);
383397
});
384398

385-
it('should just configure without touching libraryOptions', () => {
399+
it('should refresh default Cognito auth config when reconfiguring with resource config only', () => {
386400
Amplify.configure(mockResourceConfig);
387401

402+
expect(
403+
mockCognitoUserPoolsTokenProviderSetAuthConfig,
404+
).toHaveBeenCalledWith(mockResourceConfig.Auth);
405+
expect(
406+
mockCognitoUserPoolsTokenProviderSetKeyValueStorage,
407+
).toHaveBeenCalledWith(defaultStorage);
388408
expect(mockAmplifySingletonConfigure).toHaveBeenCalledWith(
389409
mockResourceConfig,
410+
{
411+
Auth: {
412+
tokenProvider: cognitoUserPoolsTokenProvider,
413+
credentialsProvider: cognitoCredentialsProvider,
414+
},
415+
},
416+
);
417+
});
418+
419+
it('should pass through when libraryOptions.Auth is provided on reconfigure', () => {
420+
const updatedResourceConfig: ResourcesConfig = {
421+
Auth: {
422+
Cognito: {
423+
userPoolClientId: 'newClientId',
424+
userPoolId: 'newPoolId',
425+
},
426+
},
427+
};
428+
const libraryOptions = {
429+
Auth: {
430+
tokenProvider: cognitoUserPoolsTokenProvider,
431+
credentialsProvider: cognitoCredentialsProvider,
432+
},
433+
};
434+
435+
Amplify.configure(updatedResourceConfig, libraryOptions);
436+
437+
expect(
438+
mockCognitoUserPoolsTokenProviderSetAuthConfig,
439+
).not.toHaveBeenCalled();
440+
expect(mockAmplifySingletonConfigure).toHaveBeenCalledWith(
441+
updatedResourceConfig,
442+
libraryOptions,
390443
);
391444
});
392445
});

packages/aws-amplify/src/initSingleton.ts

Lines changed: 13 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -48,66 +48,25 @@ export const DefaultAmplify = {
4848
)
4949
: cognitoCredentialsProvider;
5050

51-
// If no Auth config is provided, no special handling will be required, configure as is.
52-
// Otherwise, we can assume an Auth config is provided from here on.
53-
if (!resolvedResourceConfig.Auth) {
51+
if (!resolvedResourceConfig.Auth || libraryOptions?.Auth) {
5452
Amplify.configure(resolvedResourceConfig, libraryOptions);
5553

5654
return;
5755
}
5856

59-
// If Auth options are provided, always just configure as is.
60-
// Otherwise, we can assume no Auth libraryOptions were provided from here on.
61-
if (libraryOptions?.Auth) {
62-
Amplify.configure(resolvedResourceConfig, libraryOptions);
63-
64-
return;
65-
}
66-
67-
// If no Auth libraryOptions were previously configured, then always add default providers.
68-
if (!Amplify.libraryOptions.Auth) {
69-
cognitoUserPoolsTokenProvider.setAuthConfig(resolvedResourceConfig.Auth);
70-
cognitoUserPoolsTokenProvider.setKeyValueStorage(
71-
// TODO: allow configure with a public interface
72-
resolvedKeyValueStorage,
73-
);
74-
75-
Amplify.configure(resolvedResourceConfig, {
76-
...libraryOptions,
77-
Auth: {
78-
tokenProvider: cognitoUserPoolsTokenProvider,
79-
credentialsProvider: resolvedCredentialsProvider,
80-
},
81-
});
82-
83-
return;
84-
}
85-
86-
// At this point, Auth libraryOptions would have been previously configured and no overriding
87-
// Auth options were given, so we should preserve the currently configured Auth libraryOptions.
88-
if (libraryOptions) {
89-
const authLibraryOptions = Amplify.libraryOptions.Auth;
90-
// If ssr is provided through libraryOptions, we should respect the intentional reconfiguration.
91-
if (libraryOptions.ssr !== undefined) {
92-
cognitoUserPoolsTokenProvider.setKeyValueStorage(
93-
// TODO: allow configure with a public interface
94-
resolvedKeyValueStorage,
95-
);
96-
97-
authLibraryOptions.credentialsProvider = resolvedCredentialsProvider;
98-
}
99-
100-
Amplify.configure(resolvedResourceConfig, {
101-
Auth: authLibraryOptions,
102-
...libraryOptions,
103-
});
104-
105-
return;
106-
}
57+
cognitoUserPoolsTokenProvider.setAuthConfig(resolvedResourceConfig.Auth);
58+
cognitoUserPoolsTokenProvider.setKeyValueStorage(
59+
// TODO: allow configure with a public interface
60+
resolvedKeyValueStorage,
61+
);
10762

108-
// Finally, if there were no libraryOptions given at all, we should simply not touch the currently
109-
// configured libraryOptions.
110-
Amplify.configure(resolvedResourceConfig);
63+
Amplify.configure(resolvedResourceConfig, {
64+
...libraryOptions,
65+
Auth: {
66+
tokenProvider: cognitoUserPoolsTokenProvider,
67+
credentialsProvider: resolvedCredentialsProvider,
68+
},
69+
});
11170
},
11271
/**
11372
* Returns the {@link ResourcesConfig} object passed in as the `resourceConfig` parameter when calling

0 commit comments

Comments
 (0)