Skip to content

Commit

Permalink
fix(core|auth|adapterCore): use createAuthTokenRefresher ⤵️
Browse files Browse the repository at this point in the history
Now we are using the createAuthTokenRefresher for creating new instances of
the deduped token refresher function for different use cases:

1. on client: there is only one instance gets created on app load
2. on server: a new instance gets created in each context that's created by
  runWithAmplifySeverContext function
  • Loading branch information
HuiSF committed May 17, 2024
1 parent d7d33da commit 2de2895
Show file tree
Hide file tree
Showing 12 changed files with 30 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { decodeJWT } from '@aws-amplify/core/internals/utils';
import { refreshAuthTokens } from '../../../src/providers/cognito/utils/refreshAuthTokens';
import { createAuthTokenRefresher } from '../../../src/providers/cognito/utils/refreshAuthTokens';
import { CognitoAuthTokens } from '../../../src/providers/cognito/tokenProvider/types';
import { initiateAuth } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider';
import { mockAccessToken, mockRequestId } from './testUtils/data';
Expand All @@ -14,6 +14,7 @@ jest.mock(
describe('refreshToken', () => {
const mockedUsername = 'mockedUsername';
const mockedRefreshToken = 'mockedRefreshToken';
const refreshAuthTokens = createAuthTokenRefresher();
// assert mocks
const mockInitiateAuth = initiateAuth as jest.Mock;
describe('positive cases', () => {
Expand Down
3 changes: 1 addition & 2 deletions packages/auth/src/providers/cognito/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,5 @@ export {
CognitoUserPoolTokenProviderType,
TokenOrchestrator,
DefaultTokenStore,
refreshAuthTokens,
refreshAuthTokensWithoutDedupe,
createAuthTokenRefresher,
} from './tokenProvider';
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
defaultStorage,
} from '@aws-amplify/core';

import { refreshAuthTokens } from '../utils/refreshAuthTokens';
import { createAuthTokenRefresher } from '../utils/refreshAuthTokens';

import { DefaultTokenStore } from './TokenStore';
import { TokenOrchestrator } from './TokenOrchestrator';
Expand All @@ -25,7 +25,7 @@ export class CognitoUserPoolsTokenProvider
this.authTokenStore.setKeyValueStorage(defaultStorage);
this.tokenOrchestrator = new TokenOrchestrator();
this.tokenOrchestrator.setAuthTokenStore(this.authTokenStore);
this.tokenOrchestrator.setTokenRefresher(refreshAuthTokens);
this.tokenOrchestrator.setTokenRefresher(createAuthTokenRefresher());
}

getTokens(
Expand Down
5 changes: 1 addition & 4 deletions packages/auth/src/providers/cognito/tokenProvider/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

export {
refreshAuthTokens,
refreshAuthTokensWithoutDedupe,
} from '../utils/refreshAuthTokens';
export { createAuthTokenRefresher } from '../utils/refreshAuthTokens';
export { DefaultTokenStore } from './TokenStore';
export { TokenOrchestrator } from './TokenOrchestrator';
export { CognitoUserPoolTokenProviderType } from './types';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import { AuthConfig } from '@aws-amplify/core';
import {
assertTokenProviderConfig,
deDupeAsyncFunction,
decodeJWT,
dedupeAsyncFunction,
} from '@aws-amplify/core/internals/utils';

import { CognitoAuthTokens, TokenRefresher } from '../tokenProvider/types';
Expand All @@ -16,7 +16,7 @@ import { AuthError } from '../../../errors/AuthError';

import { getUserContextData } from './userContextData';

const refreshAuthTokensFunction: TokenRefresher = async ({
const refreshAuthTokens: TokenRefresher = async ({
tokens,
authConfig,
username,
Expand Down Expand Up @@ -76,5 +76,5 @@ const refreshAuthTokensFunction: TokenRefresher = async ({
};
};

export const refreshAuthTokens = deDupeAsyncFunction(refreshAuthTokensFunction);
export const refreshAuthTokensWithoutDedupe = refreshAuthTokensFunction;
export const createAuthTokenRefresher = () =>
dedupeAsyncFunction(refreshAuthTokens);
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import {
DefaultTokenStore,
TokenOrchestrator,
refreshAuthTokensWithoutDedupe,
createAuthTokenRefresher,
} from '@aws-amplify/auth/cognito';
import { AuthConfig, KeyValueStorageInterface } from '@aws-amplify/core';

Expand All @@ -27,10 +27,16 @@ const mockAuthConfig: AuthConfig = {
};
const MockDefaultTokenStore = DefaultTokenStore as jest.Mock;
const MockTokenOrchestrator = TokenOrchestrator as jest.Mock;
const mockRefreshAuthTokens = refreshAuthTokensWithoutDedupe as jest.Mock;
const mockCreateAuthTokenRefresher = createAuthTokenRefresher as jest.Mock;

describe('createUserPoolsTokenProvider', () => {
const mockRefreshTokenFunc = jest.fn();

beforeEach(() => {
mockCreateAuthTokenRefresher.mockReturnValue(mockRefreshTokenFunc);
});

afterEach(() => {
jest.resetAllMocks();
});

Expand Down Expand Up @@ -60,7 +66,7 @@ describe('createUserPoolsTokenProvider', () => {
).toHaveBeenCalledWith(mockTokenStoreInstance);
expect(
mockTokenOrchestratorInstance.setTokenRefresher,
).toHaveBeenCalledWith(mockRefreshAuthTokens);
).toHaveBeenCalledWith(mockRefreshTokenFunc);

expect(tokenProvider).toBeDefined();
});
Expand Down
3 changes: 1 addition & 2 deletions packages/aws-amplify/__tests__/exports.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,7 @@ describe('aws-amplify Exports', () => {
'DefaultIdentityIdStore',
'TokenOrchestrator',
'DefaultTokenStore',
'refreshAuthTokens',
'refreshAuthTokensWithoutDedupe',
'createAuthTokenRefresher',
].sort(),
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import {
DefaultTokenStore,
TokenOrchestrator,
refreshAuthTokensWithoutDedupe,
createAuthTokenRefresher,
} from '@aws-amplify/auth/cognito';
import {
AuthConfig,
Expand All @@ -28,7 +28,7 @@ export const createUserPoolsTokenProvider = (
const tokenOrchestrator = new TokenOrchestrator();
tokenOrchestrator.setAuthConfig(authConfig);
tokenOrchestrator.setAuthTokenStore(authTokenStore);
tokenOrchestrator.setTokenRefresher(refreshAuthTokensWithoutDedupe);
tokenOrchestrator.setTokenRefresher(createAuthTokenRefresher());

return {
getTokens: ({ forceRefresh } = { forceRefresh: false }) =>
Expand Down
10 changes: 5 additions & 5 deletions packages/core/__tests__/utils/deDupeAsyncRequests.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { deDupeAsyncFunction } from '../../src/utils/deDupeAsyncFunction';
import { dedupeAsyncFunction } from '../../src/utils/dedupeAsyncFunction';

describe('dedupeAsyncFunction()', () => {
const numberOfConcurrentCalls = 10;
Expand All @@ -13,28 +13,28 @@ describe('dedupeAsyncFunction()', () => {
});

it('should invoke the mockServiceFunction', async () => {
const deDupedFunction = deDupeAsyncFunction(mockServiceFunction);
const deDupedFunction = dedupeAsyncFunction(mockServiceFunction);

deDupedFunction();
expect(mockServiceFunction).toHaveBeenCalledTimes(1);
});

it('should invoke the mockServiceFunction one time during concurrent sync calls', () => {
const deDupedFunction = deDupeAsyncFunction(mockServiceFunction);
const deDupedFunction = dedupeAsyncFunction(mockServiceFunction);
for (let i = 0; i < numberOfConcurrentCalls; i++) {
deDupedFunction();
}
expect(mockServiceFunction).toHaveBeenCalledTimes(1);
});

it('should return a value once the mockServiceFunction is resolved', async () => {
const deDupedFunction = deDupeAsyncFunction(mockServiceFunction);
const deDupedFunction = dedupeAsyncFunction(mockServiceFunction);
expect(await deDupedFunction()).toEqual(mockReturnValue);
expect(mockServiceFunction).toHaveBeenCalledTimes(1);
});

it('should allow to invoke the mockServiceFunction again after the promise has being resolved', async () => {
const deDupedFunction = deDupeAsyncFunction(mockServiceFunction);
const deDupedFunction = dedupeAsyncFunction(mockServiceFunction);
for (let i = 0; i < numberOfConcurrentCalls; i++) {
expect(deDupedFunction()).toBeInstanceOf(Promise);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/libraryUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export {
retry,
urlSafeDecode,
urlSafeEncode,
deDupeAsyncFunction,
dedupeAsyncFunction,
} from './utils';
export { parseAWSExports } from './parseAWSExports';
export { isAmplifyOutputs, parseAmplifyOutputs } from './parseAmplifyOutputs';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @param asyncFunction - asyncFunction to be deduped.
* @returns - the return type of the callback
*/
export const deDupeAsyncFunction = <A extends any[], R>(
export const dedupeAsyncFunction = <A extends any[], R>(
asyncFunction: (...args: A) => Promise<R>,
) => {
let inflightPromise: Promise<R> | undefined;
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ export {
export { urlSafeDecode } from './urlSafeDecode';
export { urlSafeEncode } from './urlSafeEncode';
export { deepFreeze } from './deepFreeze';
export { deDupeAsyncFunction } from './deDupeAsyncFunction';
export { dedupeAsyncFunction } from './dedupeAsyncFunction';

0 comments on commit 2de2895

Please sign in to comment.