diff --git a/.github/actions/load-verdaccio-with-amplify-js/action.yml b/.github/actions/load-verdaccio-with-amplify-js/action.yml index c8cd349cb86..b0f2f5552ac 100644 --- a/.github/actions/load-verdaccio-with-amplify-js/action.yml +++ b/.github/actions/load-verdaccio-with-amplify-js/action.yml @@ -6,7 +6,8 @@ runs: steps: - name: Start verdaccio run: | - npx verdaccio@5.25.0 & + # This version supports Node.js v22 + npx verdaccio@5.31.1 & while ! nc -z localhost 4873; do echo "Verdaccio not running yet" sleep 1 @@ -18,25 +19,30 @@ runs: - name: Install and run npm-cli-login shell: bash env: - NPM_REGISTRY: http://localhost:4873/ + NPM_REGISTRY_HOST: localhost:4873 + NPM_REGISTRY: http://localhost:4873 NPM_USER: verdaccio NPM_PASS: verdaccio NPM_EMAIL: verdaccio@amplify.js run: | - npm i -g npm-cli-adduser - npm-cli-adduser - sleep 1 - - name: Configure registry and git + # Make the HTTP request that npm addUser makes to avoid the "Exit handler never called" error + TOKEN=$(curl -s \ + -H "Accept: application/json" \ + -H "Content-Type:application/json" \ + -X PUT --data "{\"name\": \"$NPM_USER\", \"password\": \"$NPM_PASS\", \"email\": \"$NPM_EMAIL\"}" \ + $NPM_REGISTRY/-/user/org.couchdb.user:$NPM_USER 2>&1 | jq -r '.token') + + # Set the Verdaccio registry and set the token for logging in + yarn config set registry $NPM_REGISTRY + npm set registry $NPM_REGISTRY + npm set //"$NPM_REGISTRY_HOST"/:_authToken $TOKEN + - name: Configure git shell: bash working-directory: ./amplify-js env: - NPM_REGISTRY: http://localhost:4873/ NPM_USER: verdaccio - NPM_PASS: verdaccio NPM_EMAIL: verdaccio@amplify.js run: | - yarn config set registry $NPM_REGISTRY - npm set registry $NPM_REGISTRY git config --global user.email $NPM_EMAIL git config --global user.name $NPM_USER git status diff --git a/.github/actions/node-and-build/action.yml b/.github/actions/node-and-build/action.yml index 0af092c4c84..becd2d49165 100644 --- a/.github/actions/node-and-build/action.yml +++ b/.github/actions/node-and-build/action.yml @@ -4,13 +4,15 @@ inputs: is-prebuild: required: false default: false + node_version: + required: false runs: using: 'composite' steps: - - name: Setup Node.js 18 + - name: Setup Node.js uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 with: - node-version: 18.20.2 + node-version: ${{ inputs.node_version || '18.x' }} env: SEGMENT_DOWNLOAD_TIMEOUT_MINS: 2 - uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 diff --git a/.github/integ-config/integ-all.yml b/.github/integ-config/integ-all.yml index c7316c37c1f..e176add9ac5 100644 --- a/.github/integ-config/integ-all.yml +++ b/.github/integ-config/integ-all.yml @@ -870,3 +870,10 @@ tests: spec: ssr-context-isolation yarn_script: ci:ssr-context-isolation browser: [chrome] + - test_name: integ_node_envs + desc: 'Node.js environment tests' + framework: node + category: integration + sample_name: auth-gql-storage + yarn_script: ci:node-env-test + node_versions: ['18.x', '20.x', '22.x'] diff --git a/.github/workflows/callable-e2e-test.yml b/.github/workflows/callable-e2e-test.yml index 18697cf5dc5..fd9f9cb697a 100644 --- a/.github/workflows/callable-e2e-test.yml +++ b/.github/workflows/callable-e2e-test.yml @@ -37,6 +37,9 @@ on: yarn_script: required: false type: string + node_versions: + required: false + type: string env: AMPLIFY_DIR: /home/runner/work/amplify-js/amplify-js/amplify-js @@ -54,6 +57,8 @@ jobs: - ${{ fromJson(inputs.browser) }} sample_name: - ${{ fromJson(inputs.sample_name) }} + node_version: + - ${{ fromJson(inputs.node_versions) }} fail-fast: false timeout-minutes: ${{ inputs.timeout_minutes }} @@ -64,6 +69,8 @@ jobs: path: amplify-js - name: Setup node and build the repository uses: ./amplify-js/.github/actions/node-and-build + with: + node_version: ${{ matrix.node_version }} - name: Setup samples staging repository uses: ./amplify-js/.github/actions/setup-samples-staging with: diff --git a/.github/workflows/callable-e2e-tests.yml b/.github/workflows/callable-e2e-tests.yml index 4ae74a69c88..477ca28b3db 100644 --- a/.github/workflows/callable-e2e-tests.yml +++ b/.github/workflows/callable-e2e-tests.yml @@ -44,6 +44,7 @@ jobs: timeout_minutes: ${{ matrix.integ-config.timeout_minutes || 35 }} retry_count: ${{ matrix.integ-config.retry_count || 3 }} yarn_script: ${{ matrix.integ-config.yarn_script || '' }} + node_versions: ${{ toJSON(matrix.integ-config.node_versions) || '[""]' }} # e2e-test-runner-headless: # name: E2E test runnner_headless diff --git a/package.json b/package.json index 2dd5ff3ff32..eaf95c79cab 100644 --- a/package.json +++ b/package.json @@ -130,6 +130,9 @@ "webpack-bundle-analyzer": "^4.7.0", "webpack-cli": "^5.0.0" }, + "engines": { + "node": ">=18" + }, "resolutions": { "@types/babel__traverse": "7.20.0", "path-scurry": "1.10.0", diff --git a/packages/api-graphql/package.json b/packages/api-graphql/package.json index ae98edafa95..7a6ed7ead52 100644 --- a/packages/api-graphql/package.json +++ b/packages/api-graphql/package.json @@ -86,7 +86,7 @@ "dependencies": { "@aws-amplify/api-rest": "4.0.47", "@aws-amplify/core": "6.4.0", - "@aws-amplify/data-schema": "^1.0.0", + "@aws-amplify/data-schema": "^1.5.0", "@aws-sdk/types": "3.387.0", "graphql": "15.8.0", "rxjs": "^7.8.1", diff --git a/packages/auth/__tests__/foundation/cognitoUserPoolEndpointResolver.test.ts b/packages/auth/__tests__/foundation/cognitoUserPoolEndpointResolver.test.ts new file mode 100644 index 00000000000..04bbff52546 --- /dev/null +++ b/packages/auth/__tests__/foundation/cognitoUserPoolEndpointResolver.test.ts @@ -0,0 +1,16 @@ +import { AmplifyUrl } from '@aws-amplify/core/internals/utils'; + +import { cognitoUserPoolEndpointResolver } from '../../src/foundation/cognitoUserPoolEndpointResolver'; +import { COGNITO_IDP_SERVICE_NAME } from '../../src/foundation/constants'; + +describe('cognitoUserPoolEndpointResolver', () => { + it('should return the Cognito User Pool endpoint', () => { + const region = 'us-west-2'; + const { url } = cognitoUserPoolEndpointResolver({ region }); + + expect(url instanceof AmplifyUrl).toBe(true); + expect(url.toString()).toEqual( + `https://${COGNITO_IDP_SERVICE_NAME}.us-west-2.amazonaws.com/`, + ); + }); +}); diff --git a/packages/auth/__tests__/foundation/factories/serviceClients/cognitoIdentityProvider/index.test.ts b/packages/auth/__tests__/foundation/factories/serviceClients/cognitoIdentityProvider/index.test.ts new file mode 100644 index 00000000000..9138718bb58 --- /dev/null +++ b/packages/auth/__tests__/foundation/factories/serviceClients/cognitoIdentityProvider/index.test.ts @@ -0,0 +1,41 @@ +import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import * as serviceClients from '../../../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { DEFAULT_SERVICE_CLIENT_API_CONFIG } from '../../../../../src/foundation/factories/serviceClients/cognitoIdentityProvider/constants'; + +import { mockServiceClientAPIConfig } from './testUtils/data'; + +jest.mock('@aws-amplify/core/internals/aws-client-utils/composers', () => ({ + ...jest.requireActual( + '@aws-amplify/core/internals/aws-client-utils/composers', + ), + composeServiceApi: jest.fn(), +})); + +export const mockComposeServiceApi = jest.mocked(composeServiceApi); + +describe('service clients', () => { + const serviceClientFactories = Object.keys(serviceClients); + + afterEach(() => { + mockComposeServiceApi.mockClear(); + }); + + test.each(serviceClientFactories)( + 'factory `%s` should invoke composeServiceApi with expected parameters', + serviceClientFactory => { + // eslint-disable-next-line import/namespace + serviceClients[serviceClientFactory](mockServiceClientAPIConfig); + + expect(mockComposeServiceApi).toHaveBeenCalledWith( + expect.any(Function), + expect.any(Function), + expect.any(Function), + expect.objectContaining({ + ...DEFAULT_SERVICE_CLIENT_API_CONFIG, + ...mockServiceClientAPIConfig, + }), + ); + }, + ); +}); diff --git a/packages/auth/__tests__/foundation/factories/serviceClients/cognitoIdentityProvider/shared/handler/cognitoUserPoolTransferHandler.test.ts b/packages/auth/__tests__/foundation/factories/serviceClients/cognitoIdentityProvider/shared/handler/cognitoUserPoolTransferHandler.test.ts new file mode 100644 index 00000000000..8f5bbc8c7f9 --- /dev/null +++ b/packages/auth/__tests__/foundation/factories/serviceClients/cognitoIdentityProvider/shared/handler/cognitoUserPoolTransferHandler.test.ts @@ -0,0 +1,43 @@ +import { unauthenticatedHandler } from '@aws-amplify/core/internals/aws-client-utils'; +import { composeTransferHandler } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import { cognitoUserPoolTransferHandler } from '../../../../../../../src/foundation/factories/serviceClients/cognitoIdentityProvider/shared/handler'; + +jest.mock('@aws-amplify/core/internals/aws-client-utils/composers'); +jest.mock('@aws-amplify/core/internals/aws-client-utils'); + +const mockComposeTransferHandler = jest.mocked(composeTransferHandler); +const mockUnauthenticatedHandler = jest.mocked(unauthenticatedHandler); + +describe('cognitoUserPoolTransferHandler', () => { + beforeAll(() => { + // need to make sure cognitoUserPoolTransferHandler is imported and used in + // the scope of the test + const _ = cognitoUserPoolTransferHandler; + }); + + it('adds the disableCacheMiddlewareFactory at module loading', () => { + expect(mockComposeTransferHandler).toHaveBeenCalledTimes(1); + + const [core, middleware] = mockComposeTransferHandler.mock.calls[0]; + + expect(core).toStrictEqual(mockUnauthenticatedHandler); + expect(middleware).toHaveLength(1); + + const disableCacheMiddlewareFactory = middleware[0] as any; + const disableCacheMiddlewarePendingNext = disableCacheMiddlewareFactory(); + + const mockNext = jest.fn(); + const disableCacheMiddleware = disableCacheMiddlewarePendingNext(mockNext); + const mockRequest = { + headers: {}, + }; + + disableCacheMiddleware(mockRequest); + + expect(mockNext).toHaveBeenCalledWith(mockRequest); + expect(mockRequest.headers).toEqual({ + 'cache-control': 'no-store', + }); + }); +}); diff --git a/packages/auth/__tests__/foundation/factories/serviceClients/cognitoIdentityProvider/shared/serde/createEmptyResponseDeserializer.test.ts b/packages/auth/__tests__/foundation/factories/serviceClients/cognitoIdentityProvider/shared/serde/createEmptyResponseDeserializer.test.ts new file mode 100644 index 00000000000..80f9ddfedb7 --- /dev/null +++ b/packages/auth/__tests__/foundation/factories/serviceClients/cognitoIdentityProvider/shared/serde/createEmptyResponseDeserializer.test.ts @@ -0,0 +1,55 @@ +import { + HttpResponse, + parseJsonError, +} from '@aws-amplify/core/internals/aws-client-utils'; + +import { createEmptyResponseDeserializer } from '../../../../../../../src/foundation/factories/serviceClients/cognitoIdentityProvider/shared/serde/createEmptyResponseDeserializer'; +import { AuthError } from '../../../../../../../src/errors/AuthError'; + +jest.mock('@aws-amplify/core/internals/aws-client-utils'); + +const mockParseJsonError = jest.mocked(parseJsonError); + +describe('createEmptyResponseDeserializer created response deserializer', () => { + const deserializer = createEmptyResponseDeserializer(); + + it('returns undefined for 2xx status code', async () => { + const response: HttpResponse = { + statusCode: 200, + body: { + json: () => Promise.resolve({}), + blob: () => Promise.resolve(new Blob()), + text: () => Promise.resolve(''), + }, + headers: {}, + }; + const output = await deserializer(response); + + expect(output).toBeUndefined(); + }); + + it('throws AuthError for 4xx status code', async () => { + const expectedErrorName = 'TestError'; + const expectedErrorMessage = 'TestErrorMessage'; + const expectedError = new Error(expectedErrorMessage); + expectedError.name = expectedErrorName; + + mockParseJsonError.mockReturnValueOnce(expectedError as any); + const response: HttpResponse = { + statusCode: 400, + body: { + json: () => Promise.resolve({}), + blob: () => Promise.resolve(new Blob()), + text: () => Promise.resolve(''), + }, + headers: {}, + }; + + expect(deserializer(response as any)).rejects.toThrow( + new AuthError({ + name: expectedErrorName, + message: expectedErrorMessage, + }), + ); + }); +}); diff --git a/packages/auth/__tests__/foundation/factories/serviceClients/cognitoIdentityProvider/shared/serde/createUserPoolDeserializer.test.ts b/packages/auth/__tests__/foundation/factories/serviceClients/cognitoIdentityProvider/shared/serde/createUserPoolDeserializer.test.ts new file mode 100644 index 00000000000..18bc775caca --- /dev/null +++ b/packages/auth/__tests__/foundation/factories/serviceClients/cognitoIdentityProvider/shared/serde/createUserPoolDeserializer.test.ts @@ -0,0 +1,59 @@ +import { + HttpResponse, + parseJsonBody, + parseJsonError, +} from '@aws-amplify/core/internals/aws-client-utils'; + +import { createUserPoolDeserializer } from '../../../../../../../src/foundation/factories/serviceClients/cognitoIdentityProvider/shared/serde/createUserPoolDeserializer'; +import { AuthError } from '../../../../../../../src/errors/AuthError'; + +jest.mock('@aws-amplify/core/internals/aws-client-utils'); + +const mockParseJsonBody = jest.mocked(parseJsonBody); +const mockParseJsonError = jest.mocked(parseJsonError); + +describe('buildUserPoolDeserializer created response deserializer', () => { + const deserializer = createUserPoolDeserializer(); + + it('returns body for 2xx status code', async () => { + const expectedBody = { test: 'test' }; + mockParseJsonBody.mockResolvedValueOnce(expectedBody); + const response: HttpResponse = { + statusCode: 200, + body: { + json: () => Promise.resolve({}), + blob: () => Promise.resolve(new Blob()), + text: () => Promise.resolve(''), + }, + headers: {}, + }; + const output = await deserializer(response); + + expect(output).toStrictEqual(expectedBody); + }); + + it('throws AuthError for 4xx status code', async () => { + const expectedErrorName = 'TestError'; + const expectedErrorMessage = 'TestErrorMessage'; + const expectedError = new Error(expectedErrorMessage); + expectedError.name = expectedErrorName; + + mockParseJsonError.mockReturnValueOnce(expectedError as any); + const response: HttpResponse = { + statusCode: 400, + body: { + json: () => Promise.resolve({}), + blob: () => Promise.resolve(new Blob()), + text: () => Promise.resolve(''), + }, + headers: {}, + }; + + expect(deserializer(response as any)).rejects.toThrow( + new AuthError({ + name: expectedErrorName, + message: expectedErrorMessage, + }), + ); + }); +}); diff --git a/packages/auth/__tests__/foundation/factories/serviceClients/cognitoIdentityProvider/shared/serde/createUserPoolSerializer.test.ts b/packages/auth/__tests__/foundation/factories/serviceClients/cognitoIdentityProvider/shared/serde/createUserPoolSerializer.test.ts new file mode 100644 index 00000000000..70d9a054a42 --- /dev/null +++ b/packages/auth/__tests__/foundation/factories/serviceClients/cognitoIdentityProvider/shared/serde/createUserPoolSerializer.test.ts @@ -0,0 +1,27 @@ +import { AmplifyUrl } from '@aws-amplify/core/internals/utils'; + +import { createUserPoolSerializer } from '../../../../../../../src/foundation/factories/serviceClients/cognitoIdentityProvider/shared/serde/createUserPoolSerializer'; + +describe('createUserPoolSerializer created request serializer', () => { + test.each(['SignUp', 'InitiateAuth', 'RevokeToken'] as const)( + `it serializes requests from operation %s`, + operation => { + const testInput = { testBody: 'testBody' }; + const testEndpoint = { + url: new AmplifyUrl('http://test.com'), + }; + const serializer = createUserPoolSerializer(operation); + const result = serializer(testInput, testEndpoint); + + expect(result).toEqual({ + method: 'POST', + url: testEndpoint.url, + headers: { + 'content-type': 'application/x-amz-json-1.1', + 'x-amz-target': `AWSCognitoIdentityProviderService.${operation}`, + }, + body: JSON.stringify(testInput), + }); + }, + ); +}); diff --git a/packages/auth/__tests__/foundation/factories/serviceClients/cognitoIdentityProvider/testUtils/data.ts b/packages/auth/__tests__/foundation/factories/serviceClients/cognitoIdentityProvider/testUtils/data.ts new file mode 100644 index 00000000000..33a9a3d5534 --- /dev/null +++ b/packages/auth/__tests__/foundation/factories/serviceClients/cognitoIdentityProvider/testUtils/data.ts @@ -0,0 +1,7 @@ +import { ServiceClientFactoryInput } from '../../../../../../src/foundation/factories/serviceClients/cognitoIdentityProvider/types'; + +export const mockServiceClientAPIConfig: ServiceClientFactoryInput = { + endpointResolver: jest.fn() as jest.MockedFunction< + ServiceClientFactoryInput['endpointResolver'] + >, +}; diff --git a/packages/auth/__tests__/foundation/parsers/regionParsers.test.ts b/packages/auth/__tests__/foundation/parsers/regionParsers.test.ts new file mode 100644 index 00000000000..978ac7d8029 --- /dev/null +++ b/packages/auth/__tests__/foundation/parsers/regionParsers.test.ts @@ -0,0 +1,47 @@ +import { AuthError } from '../../../src/errors/AuthError'; +import { + getRegionFromIdentityPoolId, + getRegionFromUserPoolId, +} from '../../../src/foundation/parsers/regionParsers'; + +describe('getRegionFromIdentityPoolId()', () => { + it('returns the region from the identity pool id', () => { + const identityPoolId = 'us-west-2:12345678-1234-1234-1234-123456789012'; + const region = getRegionFromIdentityPoolId(identityPoolId); + expect(region).toEqual('us-west-2'); + }); + + test.each([undefined, 'invalid-id-123'])( + `throws an error when the identity pool id is invalid as %p`, + identityPoolId => { + expect(() => getRegionFromIdentityPoolId(identityPoolId)).toThrow( + new AuthError({ + name: 'InvalidIdentityPoolIdException', + message: 'Invalid identity pool id provided.', + recoverySuggestion: + 'Make sure a valid identityPoolId is given in the config.', + }), + ); + }, + ); +}); + +describe('getRegionFromUserPoolId()', () => { + it('should return the region from the user pool id', () => { + const userPoolId = 'us-west-2_12345678'; + const region = getRegionFromUserPoolId(userPoolId); + expect(region).toEqual('us-west-2'); + }); + + test.each([undefined, 'invalid-id-123'])( + `throws an error when the user pool id is invalid as %p`, + userPoolId => { + expect(() => getRegionFromUserPoolId(userPoolId)).toThrow( + new AuthError({ + name: 'InvalidUserPoolId', + message: 'Invalid user pool id provided.', + }), + ); + }, + ); +}); diff --git a/packages/auth/__tests__/providers/cognito/autoSignIn.test.ts b/packages/auth/__tests__/providers/cognito/autoSignIn.test.ts index 783fc2e9699..d787c2cdedf 100644 --- a/packages/auth/__tests__/providers/cognito/autoSignIn.test.ts +++ b/packages/auth/__tests__/providers/cognito/autoSignIn.test.ts @@ -8,13 +8,10 @@ import { signUp, } from '../../../src/providers/cognito'; import { autoSignIn } from '../../../src/providers/cognito/apis/autoSignIn'; -import * as signUpClient from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; -import { - RespondToAuthChallengeCommandOutput, - SignUpCommandOutput, -} from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider/types'; import * as initiateAuthHelpers from '../../../src/providers/cognito/utils/signInHelpers'; import { AuthError } from '../../../src/errors/AuthError'; +import { createSignUpClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { RespondToAuthChallengeCommandOutput } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider/types'; import { authAPITestParams } from './testUtils/authApiTestParams'; @@ -23,6 +20,9 @@ jest.mock('@aws-amplify/core/internals/utils', () => ({ ...jest.requireActual('@aws-amplify/core/internals/utils'), isBrowser: jest.fn(() => false), })); +jest.mock( + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', +); const authConfig = { Cognito: { @@ -35,27 +35,30 @@ Amplify.configure({ Auth: authConfig, }); describe('Auto sign-in API Happy Path Cases:', () => { - let signUpSpy; - let handleUserSRPAuthflowSpy; + let handleUserSRPAuthFlowSpy: jest.SpyInstance; + + const mockSignUp = jest.fn(); + const mockCreateSignUpClient = jest.mocked(createSignUpClient); + const { user1 } = authAPITestParams; beforeEach(async () => { - signUpSpy = jest - .spyOn(signUpClient, 'signUp') - .mockImplementationOnce( - async () => ({ UserConfirmed: true }) as SignUpCommandOutput, - ); + mockSignUp.mockResolvedValueOnce({ UserConfirmed: true }); + mockCreateSignUpClient.mockReturnValueOnce(mockSignUp); - handleUserSRPAuthflowSpy = jest + handleUserSRPAuthFlowSpy = jest .spyOn(initiateAuthHelpers, 'handleUserSRPAuthFlow') .mockImplementationOnce( async (): Promise => authAPITestParams.RespondToAuthChallengeCommandOutput, ); }); + afterEach(() => { - signUpSpy.mockClear(); - handleUserSRPAuthflowSpy.mockClear(); + mockSignUp.mockClear(); + mockCreateSignUpClient.mockClear(); + handleUserSRPAuthFlowSpy.mockClear(); }); + test('signUp should enable autoSignIn and return COMPLETE_AUTO_SIGN_IN step', async () => { const resp = await signUp({ username: user1.username, @@ -71,13 +74,13 @@ describe('Auto sign-in API Happy Path Cases:', () => { signUpStep: 'COMPLETE_AUTO_SIGN_IN', }, }); - expect(signUpSpy).toHaveBeenCalledTimes(1); + expect(mockSignUp).toHaveBeenCalledTimes(1); }); test('Auto sign-in should resolve to a signIn output', async () => { const signInOutput = await autoSignIn(); expect(signInOutput).toEqual(authAPITestParams.signInResult()); - expect(handleUserSRPAuthflowSpy).toHaveBeenCalledTimes(1); + expect(handleUserSRPAuthFlowSpy).toHaveBeenCalledTimes(1); }); }); diff --git a/packages/auth/__tests__/providers/cognito/confirmResetPassword.test.ts b/packages/auth/__tests__/providers/cognito/confirmResetPassword.test.ts index df8167e5030..d07979c5d9c 100644 --- a/packages/auth/__tests__/providers/cognito/confirmResetPassword.test.ts +++ b/packages/auth/__tests__/providers/cognito/confirmResetPassword.test.ts @@ -7,7 +7,8 @@ import { AuthError } from '../../../src/errors/AuthError'; import { AuthValidationErrorCode } from '../../../src/errors/types/validation'; import { confirmResetPassword } from '../../../src/providers/cognito'; import { ConfirmForgotPasswordException } from '../../../src/providers/cognito/types/errors'; -import { confirmForgotPassword } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; +import { createConfirmForgotPasswordClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../../../src/providers/cognito/factories'; import { authAPITestParams } from './testUtils/authApiTestParams'; import { getMockError } from './testUtils/data'; @@ -22,12 +23,19 @@ jest.mock('@aws-amplify/core/internals/utils', () => ({ isBrowser: jest.fn(() => false), })); jest.mock( - '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider', + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', ); +jest.mock('../../../src/providers/cognito/factories'); describe('confirmResetPassword', () => { // assert mocks - const mockConfirmForgotPassword = confirmForgotPassword as jest.Mock; + const mockConfirmForgotPassword = jest.fn(); + const mockCreateConfirmResetPasswordClient = jest.mocked( + createConfirmForgotPasswordClient, + ); + const mockCreateCognitoUserPoolEndpointResolver = jest.mocked( + createCognitoUserPoolEndpointResolver, + ); beforeAll(() => { setUpGetConfig(Amplify); @@ -37,10 +45,15 @@ describe('confirmResetPassword', () => { mockConfirmForgotPassword.mockResolvedValue( authAPITestParams.confirmResetPasswordHttpCallResult, ); + mockCreateConfirmResetPasswordClient.mockReturnValueOnce( + mockConfirmForgotPassword, + ); }); afterEach(() => { mockConfirmForgotPassword.mockReset(); + mockCreateConfirmResetPasswordClient.mockClear(); + mockCreateCognitoUserPoolEndpointResolver.mockClear(); }); it('should call the confirmForgotPassword and return void', async () => { @@ -50,6 +63,26 @@ describe('confirmResetPassword', () => { expect(mockConfirmForgotPassword).toHaveBeenCalled(); }); + it('invokes createCognitoUserPoolEndpointResolver with expected endpointOverride', async () => { + const expectedUserPoolEndpoint = 'https://my-custom-endpoint.com'; + jest.mocked(Amplify.getConfig).mockReturnValueOnce({ + Auth: { + Cognito: { + userPoolClientId: '111111-aaaaa-42d8-891d-ee81a1549398', + userPoolId: 'us-west-2_zzzzz', + identityPoolId: 'us-west-2:xxxxxx', + userPoolEndpoint: expectedUserPoolEndpoint, + }, + }, + }); + + await confirmResetPassword(authAPITestParams.confirmResetPasswordRequest); + + expect(mockCreateCognitoUserPoolEndpointResolver).toHaveBeenCalledWith({ + endpointOverride: expectedUserPoolEndpoint, + }); + }); + it('should contain clientMetadata from request', async () => { await confirmResetPassword({ username: 'username', diff --git a/packages/auth/__tests__/providers/cognito/confirmSignInErrorCases.test.ts b/packages/auth/__tests__/providers/cognito/confirmSignInErrorCases.test.ts index 0f20b1703f3..a2d561799d9 100644 --- a/packages/auth/__tests__/providers/cognito/confirmSignInErrorCases.test.ts +++ b/packages/auth/__tests__/providers/cognito/confirmSignInErrorCases.test.ts @@ -4,8 +4,8 @@ import { AuthError } from '../../../src/errors/AuthError'; import { AuthValidationErrorCode } from '../../../src/errors/types/validation'; import { confirmSignIn } from '../../../src/providers/cognito/apis/confirmSignIn'; import { RespondToAuthChallengeException } from '../../../src/providers/cognito/types/errors'; -import { respondToAuthChallenge } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; import { signInStore } from '../../../src/providers/cognito/utils/signInStore'; +import { createRespondToAuthChallengeClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; import { getMockError } from './testUtils/data'; import { setUpGetConfig } from './testUtils/setUpGetConfig'; @@ -15,10 +15,11 @@ jest.mock('@aws-amplify/core', () => ({ ...(jest.createMockFromModule('@aws-amplify/core') as object), Amplify: { getConfig: jest.fn(() => ({})) }, })); +jest.mock('../../../src/providers/cognito/utils/signInStore'); jest.mock( - '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider', + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', ); -jest.mock('../../../src/providers/cognito/utils/signInStore'); +jest.mock('../../../src/providers/cognito/factories'); describe('confirmSignIn API error path cases:', () => { const challengeName = 'SELECT_MFA_TYPE'; @@ -26,7 +27,10 @@ describe('confirmSignIn API error path cases:', () => { const { username } = authAPITestParams.user1; // assert mocks const mockStoreGetState = signInStore.getState as jest.Mock; - const mockRespondToAuthChallenge = respondToAuthChallenge as jest.Mock; + const mockRespondToAuthChallenge = jest.fn(); + const mockCreateRespondToAuthChallengeClient = jest.mocked( + createRespondToAuthChallengeClient, + ); beforeAll(() => { setUpGetConfig(Amplify); @@ -37,8 +41,15 @@ describe('confirmSignIn API error path cases:', () => { }); }); + beforeEach(() => { + mockCreateRespondToAuthChallengeClient.mockReturnValueOnce( + mockRespondToAuthChallenge, + ); + }); + afterEach(() => { mockRespondToAuthChallenge.mockReset(); + mockCreateRespondToAuthChallengeClient.mockClear(); }); it('confirmSignIn API should throw an error when challengeResponse is empty', async () => { diff --git a/packages/auth/__tests__/providers/cognito/confirmSignInHappyCases.test.ts b/packages/auth/__tests__/providers/cognito/confirmSignInHappyCases.test.ts index ddeb3c368fd..ddfcc9c2d8e 100644 --- a/packages/auth/__tests__/providers/cognito/confirmSignInHappyCases.test.ts +++ b/packages/auth/__tests__/providers/cognito/confirmSignInHappyCases.test.ts @@ -9,16 +9,22 @@ import { signIn, } from '../../../src/providers/cognito/'; import * as signInHelpers from '../../../src/providers/cognito/utils/signInHelpers'; -import { RespondToAuthChallengeCommandOutput } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider/types'; import { cognitoUserPoolsTokenProvider, tokenOrchestrator, } from '../../../src/providers/cognito/tokenProvider'; -import * as clients from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; +import { + createInitiateAuthClient, + createRespondToAuthChallengeClient, +} from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { RespondToAuthChallengeCommandOutput } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider/types'; import { authAPITestParams } from './testUtils/authApiTestParams'; jest.mock('../../../src/providers/cognito/apis/getCurrentUser'); +jest.mock( + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', +); const authConfig = { Cognito: { @@ -35,6 +41,9 @@ describe('confirmSignIn API happy path cases', () => { let handleChallengeNameSpy: jest.SpyInstance; const { username, password } = authAPITestParams.user1; + const mockInitiateAuth = jest.fn(); + const mockCreateInitiateAuthClient = jest.mocked(createInitiateAuthClient); + beforeEach(async () => { cognitoUserPoolsTokenProvider.setAuthConfig(authConfig); @@ -56,10 +65,14 @@ describe('confirmSignIn API happy path cases', () => { $metadata: {}, }), ); + + mockCreateInitiateAuthClient.mockReturnValueOnce(mockInitiateAuth); }); afterEach(() => { handleChallengeNameSpy.mockClear(); + mockInitiateAuth.mockClear(); + mockCreateInitiateAuthClient.mockClear(); }); afterAll(() => { @@ -234,20 +247,16 @@ describe('confirmSignIn API happy path cases', () => { const mockedUserSub = '1111-2222-3333-4444'; const activeSignInSession = '1234234232'; const activeChallengeName = 'SMS_MFA'; - const initiateAuthSpy = jest - .spyOn(clients, 'initiateAuth') - .mockImplementationOnce( - async (): Promise => ({ - ChallengeName: activeChallengeName, - Session: activeSignInSession, - $metadata: {}, - ChallengeParameters: { - USER_ID_FOR_SRP: mockedUserSub, - CODE_DELIVERY_DELIVERY_MEDIUM: 'SMS', - CODE_DELIVERY_DESTINATION: '*******9878', - }, - }), - ); + mockInitiateAuth.mockResolvedValueOnce({ + ChallengeName: activeChallengeName, + Session: activeSignInSession, + $metadata: {}, + ChallengeParameters: { + USER_ID_FOR_SRP: mockedUserSub, + CODE_DELIVERY_DELIVERY_MEDIUM: 'SMS', + CODE_DELIVERY_DESTINATION: '*******9878', + }, + }); await signIn({ username, password, @@ -260,6 +269,7 @@ describe('confirmSignIn API happy path cases', () => { options: authAPITestParams.configWithClientMetadata, }); const options = authAPITestParams.configWithClientMetadata; + expect(handleChallengeNameSpy).toHaveBeenCalledWith( mockedUserSub, activeChallengeName, @@ -270,14 +280,17 @@ describe('confirmSignIn API happy path cases', () => { authAPITestParams.configWithClientMetadata.clientMetadata, options, ); - initiateAuthSpy.mockClear(); }); }); describe('Cognito ASF', () => { - let respondToAuthChallengeSpy: jest.SpyInstance; let handleUserSRPAuthFlowSpy: jest.SpyInstance; + const mockRespondToAuthChallenge = jest.fn(); + const mockCreateRespondToAuthChallengeClient = jest.mocked( + createRespondToAuthChallengeClient, + ); + const { username } = authAPITestParams.user1; const { password } = authAPITestParams.user1; beforeEach(() => { @@ -292,30 +305,28 @@ describe('Cognito ASF', () => { }, }; - respondToAuthChallengeSpy = jest - .spyOn(clients, 'respondToAuthChallenge') - .mockImplementation( - async (): Promise => { - return { - Session: '1234234232', - $metadata: {}, - ChallengeName: undefined, - ChallengeParameters: {}, - AuthenticationResult: { - AccessToken: - 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE3MTAyOTMxMzB9.YzDpgJsrB3z-ZU1XxMcXSQsMbgCzwH_e-_76rnfehh0', - ExpiresIn: 1000, - IdToken: - 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE3MTAyOTMxMzB9.YzDpgJsrB3z-ZU1XxMcXSQsMbgCzwH_e-_76rnfehh0', - RefreshToken: 'qwersfsafsfssfasf', - }, - }; - }, - ); + mockRespondToAuthChallenge.mockResolvedValueOnce({ + Session: '1234234232', + $metadata: {}, + ChallengeName: undefined, + ChallengeParameters: {}, + AuthenticationResult: { + AccessToken: + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE3MTAyOTMxMzB9.YzDpgJsrB3z-ZU1XxMcXSQsMbgCzwH_e-_76rnfehh0', + ExpiresIn: 1000, + IdToken: + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE3MTAyOTMxMzB9.YzDpgJsrB3z-ZU1XxMcXSQsMbgCzwH_e-_76rnfehh0', + RefreshToken: 'qwersfsafsfssfasf', + }, + }); + mockCreateRespondToAuthChallengeClient.mockReturnValueOnce( + mockRespondToAuthChallenge, + ); }); afterEach(() => { - respondToAuthChallengeSpy.mockClear(); + mockRespondToAuthChallenge.mockClear(); + mockCreateRespondToAuthChallengeClient.mockClear(); handleUserSRPAuthFlowSpy.mockClear(); (window as any).AmazonCognitoAdvancedSecurityData = undefined; }); @@ -342,15 +353,11 @@ describe('Cognito ASF', () => { expect(result.isSignedIn).toBe(false); expect(result.nextStep.signInStep).toBe('CONFIRM_SIGN_IN_WITH_SMS_CODE'); - try { - await confirmSignIn({ - challengeResponse: '777', - }); - } catch (err) { - console.log(err); - } - - expect(respondToAuthChallengeSpy).toHaveBeenCalledWith( + await confirmSignIn({ + challengeResponse: '777', + }); + + expect(mockRespondToAuthChallenge).toHaveBeenCalledWith( expect.objectContaining({ region: 'us-west-2', }), @@ -384,15 +391,11 @@ describe('Cognito ASF', () => { expect(result.nextStep.signInStep).toBe( 'CONTINUE_SIGN_IN_WITH_MFA_SELECTION', ); - try { - await confirmSignIn({ - challengeResponse: 'SMS', - }); - } catch (err) { - console.log(err); - } - - expect(respondToAuthChallengeSpy).toHaveBeenCalledWith( + await confirmSignIn({ + challengeResponse: 'SMS', + }); + + expect(mockRespondToAuthChallenge).toHaveBeenCalledWith( expect.objectContaining({ region: 'us-west-2', }), @@ -427,15 +430,11 @@ describe('Cognito ASF', () => { expect(result.isSignedIn).toBe(false); expect(result.nextStep.signInStep).toBe('CONFIRM_SIGN_IN_WITH_TOTP_CODE'); - try { - await confirmSignIn({ - challengeResponse: '123456', - }); - } catch (err) { - console.log(err); - } - - expect(respondToAuthChallengeSpy).toHaveBeenCalledWith( + await confirmSignIn({ + challengeResponse: '123456', + }); + + expect(mockRespondToAuthChallenge).toHaveBeenCalledWith( expect.objectContaining({ region: 'us-west-2', }), @@ -472,15 +471,11 @@ describe('Cognito ASF', () => { expect(result.nextStep.signInStep).toBe( 'CONFIRM_SIGN_IN_WITH_NEW_PASSWORD_REQUIRED', ); - try { - await confirmSignIn({ - challengeResponse: 'password', - }); - } catch (err) { - console.log(err); - } - - expect(respondToAuthChallengeSpy).toHaveBeenCalledWith( + await confirmSignIn({ + challengeResponse: 'password', + }); + + expect(mockRespondToAuthChallenge).toHaveBeenCalledWith( expect.objectContaining({ region: 'us-west-2', }), @@ -516,15 +511,11 @@ describe('Cognito ASF', () => { expect(result.nextStep.signInStep).toBe( 'CONFIRM_SIGN_IN_WITH_CUSTOM_CHALLENGE', ); - try { - await confirmSignIn({ - challengeResponse: 'secret-answer', - }); - } catch (err) { - console.log(err); - } - - expect(respondToAuthChallengeSpy).toHaveBeenCalledWith( + await confirmSignIn({ + challengeResponse: 'secret-answer', + }); + + expect(mockRespondToAuthChallenge).toHaveBeenCalledWith( expect.objectContaining({ region: 'us-west-2', }), diff --git a/packages/auth/__tests__/providers/cognito/confirmSignUp.test.ts b/packages/auth/__tests__/providers/cognito/confirmSignUp.test.ts index e6528e4b1ed..3523f9495aa 100644 --- a/packages/auth/__tests__/providers/cognito/confirmSignUp.test.ts +++ b/packages/auth/__tests__/providers/cognito/confirmSignUp.test.ts @@ -4,16 +4,22 @@ import { Amplify } from '@aws-amplify/core'; import { confirmSignUp } from '../../../src/providers/cognito'; -import { confirmSignUp as providerConfirmSignUp } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; import { AuthValidationErrorCode } from '../../../src/errors/types/validation'; import { AuthError } from '../../../src/errors/AuthError'; import { ConfirmSignUpException } from '../../../src/providers/cognito/types/errors'; -import { ConfirmSignUpCommandOutput } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider/types'; +import { createConfirmSignUpClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../../../src/providers/cognito/factories'; +import { ConfirmSignUpCommandOutput } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider/types'; import { authAPITestParams } from './testUtils/authApiTestParams'; import { getMockError } from './testUtils/data'; import { setUpGetConfig } from './testUtils/setUpGetConfig'; +jest.mock( + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', +); +jest.mock('../../../src/providers/cognito/factories'); + jest.mock('@aws-amplify/core', () => ({ ...(jest.createMockFromModule('@aws-amplify/core') as object), Amplify: { getConfig: jest.fn(() => ({})) }, @@ -22,15 +28,16 @@ jest.mock('@aws-amplify/core/internals/utils', () => ({ ...jest.requireActual('@aws-amplify/core/internals/utils'), isBrowser: jest.fn(() => false), })); -jest.mock( - '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider', -); describe('confirmSignUp', () => { const { user1 } = authAPITestParams; const confirmationCode = '123456'; // assert mocks - const mockConfirmSignUp = providerConfirmSignUp as jest.Mock; + const mockConfirmSignUp = jest.fn(); + const mockCreateConfirmSignUpClient = jest.mocked(createConfirmSignUpClient); + const mockCreateCognitoUserPoolEndpointResolver = jest.mocked( + createCognitoUserPoolEndpointResolver, + ); beforeAll(() => { setUpGetConfig(Amplify); @@ -38,10 +45,13 @@ describe('confirmSignUp', () => { beforeEach(() => { mockConfirmSignUp.mockResolvedValue({} as ConfirmSignUpCommandOutput); + mockCreateConfirmSignUpClient.mockReturnValueOnce(mockConfirmSignUp); }); afterEach(() => { mockConfirmSignUp.mockReset(); + mockCreateConfirmSignUpClient.mockClear(); + mockCreateCognitoUserPoolEndpointResolver.mockClear(); }); it('should call confirmSignUp and return a SignUpResult', async () => { @@ -68,6 +78,29 @@ describe('confirmSignUp', () => { expect(mockConfirmSignUp).toHaveBeenCalledTimes(1); }); + it('invokes mockCreateCognitoUserPoolEndpointResolver with expected endpointOverride', async () => { + const expectedUserPoolEndpoint = 'https://my-custom-endpoint.com'; + jest.mocked(Amplify.getConfig).mockReturnValueOnce({ + Auth: { + Cognito: { + userPoolClientId: '111111-aaaaa-42d8-891d-ee81a1549398', + userPoolId: 'us-west-2_zzzzz', + identityPoolId: 'us-west-2:xxxxxx', + userPoolEndpoint: expectedUserPoolEndpoint, + }, + }, + }); + + await confirmSignUp({ + username: user1.username, + confirmationCode, + }); + + expect(mockCreateCognitoUserPoolEndpointResolver).toHaveBeenCalledWith({ + endpointOverride: expectedUserPoolEndpoint, + }); + }); + it('should contain force alias creation', async () => { await confirmSignUp({ username: user1.username, diff --git a/packages/auth/__tests__/providers/cognito/confirmUserAttribute.test.ts b/packages/auth/__tests__/providers/cognito/confirmUserAttribute.test.ts index 3c7961d125a..56608241897 100644 --- a/packages/auth/__tests__/providers/cognito/confirmUserAttribute.test.ts +++ b/packages/auth/__tests__/providers/cognito/confirmUserAttribute.test.ts @@ -7,8 +7,9 @@ import { decodeJWT } from '@aws-amplify/core/internals/utils'; import { AuthError } from '../../../src/errors/AuthError'; import { confirmUserAttribute } from '../../../src/providers/cognito'; import { VerifyUserAttributeException } from '../../../src/providers/cognito/types/errors'; -import { verifyUserAttribute } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; import { AuthValidationErrorCode } from '../../../src/errors/types/validation'; +import { createVerifyUserAttributeClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../../../src/providers/cognito/factories'; import { getMockError, mockAccessToken } from './testUtils/data'; import { setUpGetConfig } from './testUtils/setUpGetConfig'; @@ -22,14 +23,21 @@ jest.mock('@aws-amplify/core/internals/utils', () => ({ isBrowser: jest.fn(() => false), })); jest.mock( - '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider', + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', ); +jest.mock('../../../src/providers/cognito/factories'); describe('confirmUserAttribute', () => { const confirmationCode = '123456'; // assert mocks const mockFetchAuthSession = fetchAuthSession as jest.Mock; - const mockVerifyUserAttribute = verifyUserAttribute as jest.Mock; + const mockVerifyUserAttribute = jest.fn(); + const mockCreateVerifyUserAttributeClient = jest.mocked( + createVerifyUserAttributeClient, + ); + const mockCreateCognitoUserPoolEndpointResolver = jest.mocked( + createCognitoUserPoolEndpointResolver, + ); beforeAll(() => { setUpGetConfig(Amplify); @@ -40,11 +48,15 @@ describe('confirmUserAttribute', () => { beforeEach(() => { mockVerifyUserAttribute.mockResolvedValue({ $metadata: {} }); + mockCreateVerifyUserAttributeClient.mockReturnValueOnce( + mockVerifyUserAttribute, + ); }); afterEach(() => { mockVerifyUserAttribute.mockReset(); mockFetchAuthSession.mockClear(); + mockCreateVerifyUserAttributeClient.mockClear(); }); it('should call the service', async () => { @@ -63,6 +75,28 @@ describe('confirmUserAttribute', () => { ); }); + it('invokes mockCreateCognitoUserPoolEndpointResolver with expected endpointOverride', async () => { + const expectedUserPoolEndpoint = 'https://my-custom-endpoint.com'; + jest.mocked(Amplify.getConfig).mockReturnValueOnce({ + Auth: { + Cognito: { + userPoolClientId: '111111-aaaaa-42d8-891d-ee81a1549398', + userPoolId: 'us-west-2_zzzzz', + identityPoolId: 'us-west-2:xxxxxx', + userPoolEndpoint: expectedUserPoolEndpoint, + }, + }, + }); + await confirmUserAttribute({ + userAttributeKey: 'email', + confirmationCode, + }); + + expect(mockCreateCognitoUserPoolEndpointResolver).toHaveBeenCalledWith({ + endpointOverride: expectedUserPoolEndpoint, + }); + }); + it('should throw an error when confirmationCode is not defined', async () => { try { await confirmUserAttribute({ diff --git a/packages/auth/__tests__/providers/cognito/deleteUser.test.ts b/packages/auth/__tests__/providers/cognito/deleteUser.test.ts index ec1cf3a90d9..b56e9736e12 100644 --- a/packages/auth/__tests__/providers/cognito/deleteUser.test.ts +++ b/packages/auth/__tests__/providers/cognito/deleteUser.test.ts @@ -7,9 +7,10 @@ import { decodeJWT } from '@aws-amplify/core/internals/utils'; import { AuthError } from '../../../src/errors/AuthError'; import { deleteUser } from '../../../src/providers/cognito'; import { tokenOrchestrator } from '../../../src/providers/cognito/tokenProvider'; -import { deleteUser as providerDeleteUser } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; import { DeleteUserException } from '../../../src/providers/cognito/types/errors'; import { signOut } from '../../../src/providers/cognito/apis/signOut'; +import { createDeleteUserClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../../../src/providers/cognito/factories'; import { getMockError, mockAccessToken } from './testUtils/data'; import { setUpGetConfig } from './testUtils/setUpGetConfig'; @@ -23,18 +24,23 @@ jest.mock('@aws-amplify/core/internals/utils', () => ({ isBrowser: jest.fn(() => false), })); jest.mock('../../../src/providers/cognito/apis/signOut'); +jest.mock('../../../src/providers/cognito/tokenProvider'); jest.mock( - '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider', + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', ); -jest.mock('../../../src/providers/cognito/tokenProvider'); +jest.mock('../../../src/providers/cognito/factories'); describe('deleteUser', () => { // assert mocks const mockFetchAuthSession = fetchAuthSession as jest.Mock; - const mockDeleteUser = providerDeleteUser as jest.Mock; + const mockDeleteUser = jest.fn(); + const mockCreateDeleteUserClient = jest.mocked(createDeleteUserClient); const mockSignOut = signOut as jest.Mock; const mockClearDeviceMetadata = tokenOrchestrator.clearDeviceMetadata as jest.Mock; + const mockCreateCognitoUserPoolEndpointResolver = jest.mocked( + createCognitoUserPoolEndpointResolver, + ); beforeAll(() => { setUpGetConfig(Amplify); @@ -45,12 +51,14 @@ describe('deleteUser', () => { beforeEach(() => { mockDeleteUser.mockResolvedValue({ $metadata: {} }); + mockCreateDeleteUserClient.mockReturnValueOnce(mockDeleteUser); }); afterEach(() => { mockDeleteUser.mockReset(); mockClearDeviceMetadata.mockClear(); mockFetchAuthSession.mockClear(); + mockCreateDeleteUserClient.mockClear(); }); it('should delete user, sign out and clear device tokens', async () => { @@ -72,6 +80,25 @@ describe('deleteUser', () => { ); }); + it('invokes mockCreateCognitoUserPoolEndpointResolver with expected endpointOverride', async () => { + const expectedUserPoolEndpoint = 'https://my-custom-endpoint.com'; + jest.mocked(Amplify.getConfig).mockReturnValueOnce({ + Auth: { + Cognito: { + userPoolClientId: '111111-aaaaa-42d8-891d-ee81a1549398', + userPoolId: 'us-west-2_zzzzz', + identityPoolId: 'us-west-2:xxxxxx', + userPoolEndpoint: expectedUserPoolEndpoint, + }, + }, + }); + await deleteUser(); + + expect(mockCreateCognitoUserPoolEndpointResolver).toHaveBeenCalledWith({ + endpointOverride: expectedUserPoolEndpoint, + }); + }); + it('should throw an error when service returns an error response', async () => { expect.assertions(2); mockDeleteUser.mockImplementation(() => { diff --git a/packages/auth/__tests__/providers/cognito/deleteUserAttributes.test.ts b/packages/auth/__tests__/providers/cognito/deleteUserAttributes.test.ts index 959592a5b87..c791b224fdb 100644 --- a/packages/auth/__tests__/providers/cognito/deleteUserAttributes.test.ts +++ b/packages/auth/__tests__/providers/cognito/deleteUserAttributes.test.ts @@ -7,7 +7,8 @@ import { decodeJWT } from '@aws-amplify/core/internals/utils'; import { AuthError } from '../../../src/errors/AuthError'; import { deleteUserAttributes } from '../../../src/providers/cognito'; import { DeleteUserAttributesException } from '../../../src/providers/cognito/types/errors'; -import { deleteUserAttributes as providerDeleteUserAttributes } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; +import { createDeleteUserAttributesClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../../../src/providers/cognito/factories'; import { getMockError, mockAccessToken } from './testUtils/data'; import { setUpGetConfig } from './testUtils/setUpGetConfig'; @@ -21,13 +22,20 @@ jest.mock('@aws-amplify/core/internals/utils', () => ({ isBrowser: jest.fn(() => false), })); jest.mock( - '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider', + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', ); +jest.mock('../../../src/providers/cognito/factories'); describe('deleteUserAttributes', () => { // assert mocks const mockFetchAuthSession = fetchAuthSession as jest.Mock; - const mockDeleteUserAttributes = providerDeleteUserAttributes as jest.Mock; + const mockDeleteUserAttributes = jest.fn(); + const mockCreateDeleteUserAttributesClient = jest.mocked( + createDeleteUserAttributesClient, + ); + const mockCreateCognitoUserPoolEndpointResolver = jest.mocked( + createCognitoUserPoolEndpointResolver, + ); beforeAll(() => { setUpGetConfig(Amplify); @@ -38,11 +46,15 @@ describe('deleteUserAttributes', () => { beforeEach(() => { mockDeleteUserAttributes.mockResolvedValue({ $metadata: {} }); + mockCreateDeleteUserAttributesClient.mockReturnValueOnce( + mockDeleteUserAttributes, + ); }); afterEach(() => { mockDeleteUserAttributes.mockReset(); mockFetchAuthSession.mockClear(); + mockCreateDeleteUserAttributesClient.mockClear(); }); it('should delete user attributes', async () => { @@ -60,6 +72,27 @@ describe('deleteUserAttributes', () => { expect(mockDeleteUserAttributes).toHaveBeenCalledTimes(1); }); + it('invokes mockCreateCognitoUserPoolEndpointResolver with expected endpointOverride', async () => { + const expectedUserPoolEndpoint = 'https://my-custom-endpoint.com'; + jest.mocked(Amplify.getConfig).mockReturnValueOnce({ + Auth: { + Cognito: { + userPoolClientId: '111111-aaaaa-42d8-891d-ee81a1549398', + userPoolId: 'us-west-2_zzzzz', + identityPoolId: 'us-west-2:xxxxxx', + userPoolEndpoint: expectedUserPoolEndpoint, + }, + }, + }); + await deleteUserAttributes({ + userAttributeKeys: ['given_name', 'address'], + }); + + expect(mockCreateCognitoUserPoolEndpointResolver).toHaveBeenCalledWith({ + endpointOverride: expectedUserPoolEndpoint, + }); + }); + it('should throw an error when service returns an error response', async () => { expect.assertions(2); mockDeleteUserAttributes.mockImplementation(() => { diff --git a/packages/auth/__tests__/providers/cognito/factories/createCognitoUserPoolEndpointResolver.test.ts b/packages/auth/__tests__/providers/cognito/factories/createCognitoUserPoolEndpointResolver.test.ts new file mode 100644 index 00000000000..1c499146921 --- /dev/null +++ b/packages/auth/__tests__/providers/cognito/factories/createCognitoUserPoolEndpointResolver.test.ts @@ -0,0 +1,55 @@ +import { AmplifyUrl } from '@aws-amplify/core/internals/utils'; + +import { cognitoUserPoolEndpointResolver } from '../../../../src/foundation/cognitoUserPoolEndpointResolver'; +import { createCognitoUserPoolEndpointResolver } from '../../../../src/providers/cognito/factories/createCognitoUserPoolEndpointResolver'; + +jest.mock('../../../../src/foundation/cognitoUserPoolEndpointResolver'); + +const mockCognitoUserPoolEndpointResolver = jest.mocked( + cognitoUserPoolEndpointResolver, +); + +describe('createCognitoUserPoolEndpointResolver()', () => { + afterEach(() => { + mockCognitoUserPoolEndpointResolver.mockClear(); + }); + + describe('creating a resolver with overrideEndpoint as `undefined`', () => { + const resolver = createCognitoUserPoolEndpointResolver({ + endpointOverride: undefined, + }); + + it('invokes cognitoUserPoolEndpointResolver with the expected region', () => { + const expectedReturningUrl = { + url: new AmplifyUrl('https://cognito-idp.us-west-2.amazonaws.com/'), + }; + mockCognitoUserPoolEndpointResolver.mockReturnValueOnce( + expectedReturningUrl, + ); + + const expectedRegion = 'us-west-2'; + const { url } = resolver({ region: expectedRegion }); + + expect(mockCognitoUserPoolEndpointResolver).toHaveBeenCalledWith({ + region: expectedRegion, + }); + expect(url).toStrictEqual(expectedReturningUrl.url); + }); + }); + + describe('creating a resolver with overrideEndpoint', () => { + const endpointOverride = 'https://cognito-idp.example.com'; + const resolver = createCognitoUserPoolEndpointResolver({ + endpointOverride, + }); + + it('returns the endpoint override', () => { + const expectedRegion = 'us-west-2'; + const { url } = resolver({ region: expectedRegion }); + expect(mockCognitoUserPoolEndpointResolver).not.toHaveBeenCalled(); + expect(url).toStrictEqual( + new AmplifyUrl('https://cognito-idp.example.com'), + ); + }); + }); +}); diff --git a/packages/auth/__tests__/providers/cognito/fetchDevices.test.ts b/packages/auth/__tests__/providers/cognito/fetchDevices.test.ts index 1e8a48ab84e..4cdb79a13bd 100644 --- a/packages/auth/__tests__/providers/cognito/fetchDevices.test.ts +++ b/packages/auth/__tests__/providers/cognito/fetchDevices.test.ts @@ -6,8 +6,9 @@ import { decodeJWT } from '@aws-amplify/core/internals/utils'; import { AuthError } from '../../../src/errors/AuthError'; import { fetchDevices } from '../../../src/providers/cognito'; -import { listDevices } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; import { ListDevicesException } from '../../../src/providers/cognito/types/errors'; +import { createListDevicesClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../../../src/providers/cognito/factories'; import { getMockError, mockAccessToken } from './testUtils/data'; import { setUpGetConfig } from './testUtils/setUpGetConfig'; @@ -21,8 +22,9 @@ jest.mock('@aws-amplify/core/internals/utils', () => ({ isBrowser: jest.fn(() => false), })); jest.mock( - '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider', + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', ); +jest.mock('../../../src/providers/cognito/factories'); describe('fetchDevices', () => { const dateEpoch = 1.696296885807e9; @@ -51,7 +53,11 @@ describe('fetchDevices', () => { }; // assert mocks const mockFetchAuthSession = fetchAuthSession as jest.Mock; - const mockListDevices = listDevices as jest.Mock; + const mockListDevices = jest.fn(); + const mockCreateListDevicesClient = jest.mocked(createListDevicesClient); + const mockCreateCognitoUserPoolEndpointResolver = jest.mocked( + createCognitoUserPoolEndpointResolver, + ); beforeAll(() => { setUpGetConfig(Amplify); @@ -65,11 +71,13 @@ describe('fetchDevices', () => { Devices: [clientResponseDevice], $metadata: {}, }); + mockCreateListDevicesClient.mockReturnValueOnce(mockListDevices); }); afterEach(() => { mockListDevices.mockReset(); mockFetchAuthSession.mockClear(); + mockCreateListDevicesClient.mockClear(); }); it('should fetch devices and parse client response correctly', async () => { @@ -84,6 +92,25 @@ describe('fetchDevices', () => { expect(mockListDevices).toHaveBeenCalledTimes(1); }); + it('invokes mockCreateCognitoUserPoolEndpointResolver with expected endpointOverride', async () => { + const expectedUserPoolEndpoint = 'https://my-custom-endpoint.com'; + jest.mocked(Amplify.getConfig).mockReturnValueOnce({ + Auth: { + Cognito: { + userPoolClientId: '111111-aaaaa-42d8-891d-ee81a1549398', + userPoolId: 'us-west-2_zzzzz', + identityPoolId: 'us-west-2:xxxxxx', + userPoolEndpoint: expectedUserPoolEndpoint, + }, + }, + }); + await fetchDevices(); + + expect(mockCreateCognitoUserPoolEndpointResolver).toHaveBeenCalledWith({ + endpointOverride: expectedUserPoolEndpoint, + }); + }); + it('should throw an error when service returns an error response', async () => { expect.assertions(2); mockListDevices.mockImplementation(() => { diff --git a/packages/auth/__tests__/providers/cognito/fetchMFAPreference.test.ts b/packages/auth/__tests__/providers/cognito/fetchMFAPreference.test.ts index ed2517a358e..c4d8a7a9efa 100644 --- a/packages/auth/__tests__/providers/cognito/fetchMFAPreference.test.ts +++ b/packages/auth/__tests__/providers/cognito/fetchMFAPreference.test.ts @@ -4,10 +4,11 @@ import { Amplify, fetchAuthSession } from '@aws-amplify/core'; import { decodeJWT } from '@aws-amplify/core/internals/utils'; -import { getUser } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; import { AuthError } from '../../../src/errors/AuthError'; import { fetchMFAPreference } from '../../../src/providers/cognito/apis/fetchMFAPreference'; import { GetUserException } from '../../../src/providers/cognito/types/errors'; +import { createGetUserClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../../../src/providers/cognito/factories'; import { getMockError, mockAccessToken } from './testUtils/data'; import { setUpGetConfig } from './testUtils/setUpGetConfig'; @@ -17,13 +18,18 @@ jest.mock('@aws-amplify/core', () => ({ Amplify: { getConfig: jest.fn(() => ({})) }, })); jest.mock( - '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider', + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', ); +jest.mock('../../../src/providers/cognito/factories'); describe('fetchMFAPreference', () => { // assert mocks const mockFetchAuthSession = fetchAuthSession as jest.Mock; - const mockGetUser = getUser as jest.Mock; + const mockGetUser = jest.fn(); + const mockCreateGetUserClient = jest.mocked(createGetUserClient); + const mockCreateCognitoUserPoolEndpointResolver = jest.mocked( + createCognitoUserPoolEndpointResolver, + ); beforeAll(() => { setUpGetConfig(Amplify); @@ -40,6 +46,7 @@ describe('fetchMFAPreference', () => { UserMFASettingList: ['SMS_MFA', 'SOFTWARE_TOKEN_MFA'], $metadata: {}, }); + mockCreateGetUserClient.mockReturnValueOnce(mockGetUser); }); afterEach(() => { @@ -62,6 +69,25 @@ describe('fetchMFAPreference', () => { ); }); + it('invokes mockCreateCognitoUserPoolEndpointResolver with expected endpointOverride', async () => { + const expectedUserPoolEndpoint = 'https://my-custom-endpoint.com'; + jest.mocked(Amplify.getConfig).mockReturnValueOnce({ + Auth: { + Cognito: { + userPoolClientId: '111111-aaaaa-42d8-891d-ee81a1549398', + userPoolId: 'us-west-2_zzzzz', + identityPoolId: 'us-west-2:xxxxxx', + userPoolEndpoint: expectedUserPoolEndpoint, + }, + }, + }); + await fetchMFAPreference(); + + expect(mockCreateCognitoUserPoolEndpointResolver).toHaveBeenCalledWith({ + endpointOverride: expectedUserPoolEndpoint, + }); + }); + it('should throw an error when service returns an error response', async () => { expect.assertions(2); mockGetUser.mockImplementation(() => { diff --git a/packages/auth/__tests__/providers/cognito/fetchUserAttributes.test.ts b/packages/auth/__tests__/providers/cognito/fetchUserAttributes.test.ts index cff5ff01b64..87cf79e715d 100644 --- a/packages/auth/__tests__/providers/cognito/fetchUserAttributes.test.ts +++ b/packages/auth/__tests__/providers/cognito/fetchUserAttributes.test.ts @@ -4,10 +4,11 @@ import { Amplify } from '@aws-amplify/core'; import { decodeJWT, fetchAuthSession } from '@aws-amplify/core/internals/utils'; -import { getUser } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; import { AuthError } from '../../../src/errors/AuthError'; import { GetUserException } from '../../../src/providers/cognito/types/errors'; import { fetchUserAttributes } from '../../../src/providers/cognito/apis/fetchUserAttributes'; +import { createGetUserClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../../../src/providers/cognito/factories'; import { getMockError, mockAccessToken } from './testUtils/data'; import { setUpGetConfig } from './testUtils/setUpGetConfig'; @@ -21,13 +22,18 @@ jest.mock('@aws-amplify/core/internals/utils', () => ({ fetchAuthSession: jest.fn(), })); jest.mock( - '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider', + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', ); +jest.mock('../../../src/providers/cognito/factories'); describe('fetchUserAttributes', () => { // assert mocks const mockFetchAuthSession = fetchAuthSession as jest.Mock; - const mockGetUser = getUser as jest.Mock; + const mockGetUser = jest.fn(); + const mockCreateGetUserClient = jest.mocked(createGetUserClient); + const mockCreateCognitoUserPoolEndpointResolver = jest.mocked( + createCognitoUserPoolEndpointResolver, + ); beforeAll(() => { setUpGetConfig(Amplify); @@ -47,11 +53,13 @@ describe('fetchUserAttributes', () => { UserMFASettingList: ['SMS_MFA', 'SOFTWARE_TOKEN_MFA'], $metadata: {}, }); + mockCreateGetUserClient.mockReturnValueOnce(mockGetUser); }); afterEach(() => { mockGetUser.mockReset(); mockFetchAuthSession.mockClear(); + mockCreateGetUserClient.mockClear(); }); it('should return the current user attributes into a map format', async () => { @@ -71,6 +79,25 @@ describe('fetchUserAttributes', () => { ); }); + it('invokes mockCreateCognitoUserPoolEndpointResolver with expected endpointOverride', async () => { + const expectedUserPoolEndpoint = 'https://my-custom-endpoint.com'; + jest.mocked(Amplify.getConfig).mockReturnValueOnce({ + Auth: { + Cognito: { + userPoolClientId: '111111-aaaaa-42d8-891d-ee81a1549398', + userPoolId: 'us-west-2_zzzzz', + identityPoolId: 'us-west-2:xxxxxx', + userPoolEndpoint: expectedUserPoolEndpoint, + }, + }, + }); + await fetchUserAttributes(); + + expect(mockCreateCognitoUserPoolEndpointResolver).toHaveBeenCalledWith({ + endpointOverride: expectedUserPoolEndpoint, + }); + }); + it('should throw an error when service returns an error response', async () => { expect.assertions(2); mockGetUser.mockImplementation(() => { diff --git a/packages/auth/__tests__/providers/cognito/forgetDevice.test.ts b/packages/auth/__tests__/providers/cognito/forgetDevice.test.ts index 6371e2b41a8..cc0a2d37407 100644 --- a/packages/auth/__tests__/providers/cognito/forgetDevice.test.ts +++ b/packages/auth/__tests__/providers/cognito/forgetDevice.test.ts @@ -8,8 +8,9 @@ import { AuthError } from '../../../src/errors/AuthError'; import { DEVICE_METADATA_NOT_FOUND_EXCEPTION } from '../../../src/errors/constants'; import { forgetDevice } from '../../../src/providers/cognito'; import { ForgetDeviceException } from '../../../src/providers/cognito/types/errors'; -import { forgetDevice as providerForgetDevice } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; import { tokenOrchestrator } from '../../../src/providers/cognito/tokenProvider'; +import { createForgetDeviceClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../../../src/providers/cognito/factories'; import { getMockError, mockAccessToken } from './testUtils/data'; import { setUpGetConfig } from './testUtils/setUpGetConfig'; @@ -22,10 +23,11 @@ jest.mock('@aws-amplify/core/internals/utils', () => ({ ...jest.requireActual('@aws-amplify/core/internals/utils'), isBrowser: jest.fn(() => false), })); +jest.mock('../../../src/providers/cognito/tokenProvider'); jest.mock( - '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider', + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', ); -jest.mock('../../../src/providers/cognito/tokenProvider'); +jest.mock('../../../src/providers/cognito/factories'); describe('fetchMFAPreference', () => { const mockDeviceMetadata = { @@ -35,11 +37,15 @@ describe('fetchMFAPreference', () => { }; // assert mocks const mockFetchAuthSession = fetchAuthSession as jest.Mock; - const mockForgetDevice = providerForgetDevice as jest.Mock; + const mockForgetDevice = jest.fn(); + const mockCreateForgetDeviceClient = jest.mocked(createForgetDeviceClient); const mockClearDeviceMetadata = tokenOrchestrator.clearDeviceMetadata as jest.Mock; const mockGetDeviceMetadata = tokenOrchestrator.getDeviceMetadata as jest.Mock; + const mockCreateCognitoUserPoolEndpointResolver = jest.mocked( + createCognitoUserPoolEndpointResolver, + ); beforeAll(() => { setUpGetConfig(Amplify); @@ -51,6 +57,7 @@ describe('fetchMFAPreference', () => { beforeEach(() => { mockForgetDevice.mockResolvedValue({ $metadata: {} }); mockGetDeviceMetadata.mockResolvedValue(mockDeviceMetadata); + mockCreateForgetDeviceClient.mockReturnValueOnce(mockForgetDevice); }); afterEach(() => { @@ -58,6 +65,7 @@ describe('fetchMFAPreference', () => { mockGetDeviceMetadata.mockReset(); mockFetchAuthSession.mockClear(); mockClearDeviceMetadata.mockClear(); + mockCreateForgetDeviceClient.mockClear(); }); it(`should forget 'external device' 'with' inputParams when tokenStore deviceMetadata 'present'`, async () => { @@ -74,6 +82,25 @@ describe('fetchMFAPreference', () => { expect(mockClearDeviceMetadata).not.toHaveBeenCalled(); }); + it('invokes mockCreateCognitoUserPoolEndpointResolver with expected endpointOverride', async () => { + const expectedUserPoolEndpoint = 'https://my-custom-endpoint.com'; + jest.mocked(Amplify.getConfig).mockReturnValueOnce({ + Auth: { + Cognito: { + userPoolClientId: '111111-aaaaa-42d8-891d-ee81a1549398', + userPoolId: 'us-west-2_zzzzz', + identityPoolId: 'us-west-2:xxxxxx', + userPoolEndpoint: expectedUserPoolEndpoint, + }, + }, + }); + await forgetDevice({ device: { id: 'externalDeviceKey' } }); + + expect(mockCreateCognitoUserPoolEndpointResolver).toHaveBeenCalledWith({ + endpointOverride: expectedUserPoolEndpoint, + }); + }); + it(`should forget 'current device' 'with' inputParams when tokenStore deviceMetadata 'present'`, async () => { expect.assertions(3); await forgetDevice({ device: { id: mockDeviceMetadata.deviceKey } }); diff --git a/packages/auth/__tests__/providers/cognito/getNewDeviceMetadata.test.ts b/packages/auth/__tests__/providers/cognito/getNewDeviceMetadata.test.ts index cb600ce133e..6058fc363b7 100644 --- a/packages/auth/__tests__/providers/cognito/getNewDeviceMetadata.test.ts +++ b/packages/auth/__tests__/providers/cognito/getNewDeviceMetadata.test.ts @@ -5,11 +5,17 @@ import { Amplify } from '@aws-amplify/core'; import { AuthError } from '../../../src/errors/AuthError'; import { ConfirmDeviceException } from '../../../src/providers/cognito/types/errors'; -import * as clients from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; -import { ConfirmDeviceCommandOutput } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider/types'; -import { getNewDeviceMetatada } from '../../../src/providers/cognito/utils/signInHelpers'; +import { getNewDeviceMetadata } from '../../../src/providers/cognito/utils/signInHelpers'; +import { createCognitoUserPoolEndpointResolver } from '../../../src/providers/cognito/factories'; +import { createConfirmDeviceClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; + +jest.mock('../../../src/providers/cognito/factories'); +jest.mock( + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', +); const userPoolId = 'us-west-2_zzzzz'; + Amplify.configure({ Auth: { Cognito: { @@ -22,66 +28,95 @@ Amplify.configure({ const mockedAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c'; +const mockCreateCognitoUserPoolEndpointResolver = jest.mocked( + createCognitoUserPoolEndpointResolver, +); + describe('test getNewDeviceMetadata API', () => { + const mockConfirmDevice = jest.fn(); + const mockCreateConfirmDeviceClient = jest.mocked(createConfirmDeviceClient); + + beforeEach(() => { + mockCreateConfirmDeviceClient.mockReturnValueOnce(mockConfirmDevice); + }); + + afterEach(() => { + mockConfirmDevice.mockClear(); + mockCreateConfirmDeviceClient.mockClear(); + }); + test('getNewDeviceMetadata should call confirmDevice and return DeviceMetadata', async () => { - const confirmDeviceClientSpy = jest - .spyOn(clients, 'confirmDevice') - .mockImplementationOnce(async (): Promise => { - return { UserConfirmationNecessary: true, $metadata: {} }; - }); + mockConfirmDevice.mockResolvedValueOnce({ + UserConfirmationNecessary: true, + $metadata: {}, + }); + const mockedDeviceKey = 'mockedDeviceKey'; const mockedGroupDeviceKey = 'mockedGroupDeviceKey'; - const deviceMetadata = await getNewDeviceMetatada( + const deviceMetadata = await getNewDeviceMetadata({ userPoolId, - { + userPoolEndpoint: undefined, + newDeviceMetadata: { DeviceKey: mockedDeviceKey, DeviceGroupKey: mockedGroupDeviceKey, }, - mockedAccessToken, - ); + accessToken: mockedAccessToken, + }); expect(deviceMetadata?.deviceKey).toBe(mockedDeviceKey); expect(deviceMetadata?.deviceGroupKey).toBe(mockedGroupDeviceKey); - expect(confirmDeviceClientSpy).toHaveBeenCalledWith( + expect(mockConfirmDevice).toHaveBeenCalledWith( expect.objectContaining({ region: 'us-west-2' }), expect.objectContaining({ AccessToken: mockedAccessToken, DeviceKey: mockedDeviceKey, }), ); - - confirmDeviceClientSpy.mockClear(); }); test('getNewDeviceMetadata should return undefined when ConfirmDevice throws an error', async () => { - const confirmDeviceClientSpy = jest - .spyOn(clients, 'confirmDevice') - .mockImplementationOnce(async (): Promise => { - throw new AuthError({ - name: ConfirmDeviceException.InternalErrorException, - message: 'error while calling confirmDevice', - }); - }); + mockConfirmDevice.mockRejectedValueOnce( + new AuthError({ + name: ConfirmDeviceException.InternalErrorException, + message: 'error while calling confirmDevice', + }), + ); const mockedDeviceKey = 'mockedDeviceKey'; const mockedGroupDeviceKey = 'mockedGroupDeviceKey'; - const deviceMetadata = await getNewDeviceMetatada( + const deviceMetadata = await getNewDeviceMetadata({ userPoolId, - { + userPoolEndpoint: undefined, + newDeviceMetadata: { DeviceKey: mockedDeviceKey, DeviceGroupKey: mockedGroupDeviceKey, }, - mockedAccessToken, - ); + accessToken: mockedAccessToken, + }); expect(deviceMetadata).toBeUndefined(); - expect(confirmDeviceClientSpy).toHaveBeenCalledWith( + expect(mockConfirmDevice).toHaveBeenCalledWith( expect.objectContaining({ region: 'us-west-2' }), expect.objectContaining({ AccessToken: mockedAccessToken, DeviceKey: mockedDeviceKey, }), ); + }); + + it('invokes createCognitoUserPoolEndpointResolver with expected userPoolEndpoint parameter', async () => { + const expectedEndpoint = 'https://custom-endpoint.com'; + await getNewDeviceMetadata({ + userPoolId, + userPoolEndpoint: expectedEndpoint, + newDeviceMetadata: { + DeviceKey: 'devicekey', + DeviceGroupKey: 'groupkey', + }, + accessToken: mockedAccessToken, + }); - confirmDeviceClientSpy.mockClear(); + expect(mockCreateCognitoUserPoolEndpointResolver).toHaveBeenCalledWith({ + endpointOverride: expectedEndpoint, + }); }); }); diff --git a/packages/auth/__tests__/providers/cognito/refreshToken.test.ts b/packages/auth/__tests__/providers/cognito/refreshToken.test.ts index 86ac80a1fee..bef5cb28d61 100644 --- a/packages/auth/__tests__/providers/cognito/refreshToken.test.ts +++ b/packages/auth/__tests__/providers/cognito/refreshToken.test.ts @@ -2,23 +2,39 @@ import { decodeJWT } from '@aws-amplify/core/internals/utils'; import { refreshAuthTokens } from '../../../src/providers/cognito/utils/refreshAuthTokens'; import { CognitoAuthTokens } from '../../../src/providers/cognito/tokenProvider/types'; -import { initiateAuth } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; import { oAuthTokenRefreshException, tokenRefreshException, } from '../../../src/providers/cognito/utils/types'; +import { createInitiateAuthClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../../../src/providers/cognito/factories'; import { mockAccessToken, mockRequestId } from './testUtils/data'; jest.mock( - '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider', + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', +); +jest.mock('../../../src/providers/cognito/factories'); + +const mockCreateInitiateAuthClient = jest.mocked(createInitiateAuthClient); +const mockCreateCognitoUserPoolEndpointResolver = jest.mocked( + createCognitoUserPoolEndpointResolver, ); describe('refreshToken', () => { const mockedUsername = 'mockedUsername'; const mockedRefreshToken = 'mockedRefreshToken'; - // assert mocks - const mockInitiateAuth = initiateAuth as jest.Mock; + const mockInitiateAuth = jest.fn(); + + beforeEach(() => { + mockCreateInitiateAuthClient.mockReturnValueOnce(mockInitiateAuth); + }); + + afterEach(() => { + mockCreateInitiateAuthClient.mockClear(); + mockCreateCognitoUserPoolEndpointResolver.mockClear(); + }); + describe('positive cases', () => { beforeEach(() => { mockInitiateAuth.mockResolvedValue({ @@ -119,6 +135,39 @@ describe('refreshToken', () => { ); (window as any).AmazonCognitoAdvancedSecurityData = undefined; }); + + it('invokes mockCreateCognitoUserPoolEndpointResolver with expected parameters', async () => { + const expectedParam = 'https://my-custom-endpoint.com'; + const expectedEndpointResolver = jest.fn(); + mockCreateCognitoUserPoolEndpointResolver.mockReturnValueOnce( + expectedEndpointResolver, + ); + + await refreshAuthTokens({ + username: 'username', + tokens: { + accessToken: { payload: {} }, + idToken: { payload: {} }, + clockDrift: 0, + refreshToken: 'refreshtoken', + username: 'username', + }, + authConfig: { + Cognito: { + userPoolId: 'us-east-1_aaaaaaa', + userPoolClientId: 'aaaaaaaaaaaa', + userPoolEndpoint: expectedParam, + }, + }, + }); + + expect(mockCreateCognitoUserPoolEndpointResolver).toHaveBeenCalledWith({ + endpointOverride: expectedParam, + }); + expect(mockCreateInitiateAuthClient).toHaveBeenCalledWith({ + endpointResolver: expectedEndpointResolver, + }); + }); }); describe('negative cases', () => { @@ -153,6 +202,7 @@ describe('refreshToken', () => { }), ).rejects.toThrow(oAuthTokenRefreshException); }); + it('should throw an exception when cognito tokens are not available', async () => { await expect( refreshAuthTokens({ diff --git a/packages/auth/__tests__/providers/cognito/rememberDevice.test.ts b/packages/auth/__tests__/providers/cognito/rememberDevice.test.ts index 820b2a1ef5f..0521e928654 100644 --- a/packages/auth/__tests__/providers/cognito/rememberDevice.test.ts +++ b/packages/auth/__tests__/providers/cognito/rememberDevice.test.ts @@ -7,9 +7,10 @@ import { Amplify, fetchAuthSession } from '@aws-amplify/core'; import { AuthError } from '../../../src/errors/AuthError'; import { rememberDevice } from '../../../src/providers/cognito'; import { UpdateDeviceStatusException } from '../../../src/providers/cognito/types/errors'; -import { updateDeviceStatus } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; import { tokenOrchestrator } from '../../../src/providers/cognito/tokenProvider'; import { DeviceMetadata } from '../../../src/providers/cognito/tokenProvider/types'; +import { createUpdateDeviceStatusClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../../../src/providers/cognito/factories'; import { getMockError, mockAccessToken } from './testUtils/data'; import { setUpGetConfig } from './testUtils/setUpGetConfig'; @@ -23,8 +24,9 @@ jest.mock('@aws-amplify/core/internals/utils', () => ({ isBrowser: jest.fn(() => false), })); jest.mock( - '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider', + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', ); +jest.mock('../../../src/providers/cognito/factories'); jest.mock('../../../src/providers/cognito/tokenProvider'); describe('rememberDevice', () => { @@ -35,7 +37,13 @@ describe('rememberDevice', () => { }; // assert mocks const mockFetchAuthSession = fetchAuthSession as jest.Mock; - const mockUpdateDeviceStatus = updateDeviceStatus as jest.Mock; + const mockUpdateDeviceStatus = jest.fn(); + const mockCreateUpdateDeviceStatusClient = jest.mocked( + createUpdateDeviceStatusClient, + ); + const mockCreateCognitoUserPoolEndpointResolver = jest.mocked( + createCognitoUserPoolEndpointResolver, + ); const mockGetDeviceMetadata = tokenOrchestrator.getDeviceMetadata as jest.Mock; @@ -49,12 +57,16 @@ describe('rememberDevice', () => { beforeEach(() => { mockGetDeviceMetadata.mockResolvedValue(mockDeviceMetadata); mockUpdateDeviceStatus.mockResolvedValue({ $metadata: {} }); + mockCreateUpdateDeviceStatusClient.mockReturnValueOnce( + mockUpdateDeviceStatus, + ); }); afterEach(() => { mockGetDeviceMetadata.mockReset(); mockUpdateDeviceStatus.mockReset(); mockFetchAuthSession.mockClear(); + mockCreateUpdateDeviceStatusClient.mockClear(); }); it('should call updateDeviceStatus client with correct request', async () => { @@ -71,6 +83,25 @@ describe('rememberDevice', () => { expect(mockUpdateDeviceStatus).toHaveBeenCalledTimes(1); }); + it('invokes mockCreateCognitoUserPoolEndpointResolver with expected endpointOverride', async () => { + const expectedUserPoolEndpoint = 'https://my-custom-endpoint.com'; + jest.mocked(Amplify.getConfig).mockReturnValueOnce({ + Auth: { + Cognito: { + userPoolClientId: '111111-aaaaa-42d8-891d-ee81a1549398', + userPoolId: 'us-west-2_zzzzz', + identityPoolId: 'us-west-2:xxxxxx', + userPoolEndpoint: expectedUserPoolEndpoint, + }, + }, + }); + await rememberDevice(); + + expect(mockCreateCognitoUserPoolEndpointResolver).toHaveBeenCalledWith({ + endpointOverride: expectedUserPoolEndpoint, + }); + }); + it('should throw an error when service returns an error response', async () => { expect.assertions(2); mockUpdateDeviceStatus.mockImplementation(() => { diff --git a/packages/auth/__tests__/providers/cognito/resendSignUpCode.test.ts b/packages/auth/__tests__/providers/cognito/resendSignUpCode.test.ts index d723a69eda8..d351a950484 100644 --- a/packages/auth/__tests__/providers/cognito/resendSignUpCode.test.ts +++ b/packages/auth/__tests__/providers/cognito/resendSignUpCode.test.ts @@ -7,7 +7,8 @@ import { resendSignUpCode } from '../../../src/providers/cognito'; import { AuthValidationErrorCode } from '../../../src/errors/types/validation'; import { AuthError } from '../../../src/errors/AuthError'; import { ResendConfirmationException } from '../../../src/providers/cognito/types/errors'; -import { resendConfirmationCode } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; +import { createResendConfirmationCodeClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../../../src/providers/cognito/factories'; import { authAPITestParams } from './testUtils/authApiTestParams'; import { getMockError } from './testUtils/data'; @@ -22,13 +23,20 @@ jest.mock('@aws-amplify/core/internals/utils', () => ({ isBrowser: jest.fn(() => false), })); jest.mock( - '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider', + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', ); +jest.mock('../../../src/providers/cognito/factories'); describe('resendSignUpCode', () => { const { user1 } = authAPITestParams; // assert mocks - const mockResendConfirmationCode = resendConfirmationCode as jest.Mock; + const mockResendConfirmationCode = jest.fn(); + const mockCreateResendConfirmationCodeClient = jest.mocked( + createResendConfirmationCodeClient, + ); + const mockCreateCognitoUserPoolEndpointResolver = jest.mocked( + createCognitoUserPoolEndpointResolver, + ); beforeAll(() => { setUpGetConfig(Amplify); @@ -38,6 +46,9 @@ describe('resendSignUpCode', () => { mockResendConfirmationCode.mockResolvedValue( authAPITestParams.resendSignUpClientResult, ); + mockCreateResendConfirmationCodeClient.mockReturnValueOnce( + mockResendConfirmationCode, + ); }); afterEach(() => { @@ -63,6 +74,26 @@ describe('resendSignUpCode', () => { expect(mockResendConfirmationCode).toHaveBeenCalledTimes(1); }); + it('invokes createCognitoUserPoolEndpointResolver with expected endpointOverride', async () => { + const expectedUserPoolEndpoint = 'https://my-custom-endpoint.com'; + jest.mocked(Amplify.getConfig).mockReturnValueOnce({ + Auth: { + Cognito: { + userPoolClientId: '111111-aaaaa-42d8-891d-ee81a1549398', + userPoolId: 'us-west-2_zzzzz', + identityPoolId: 'us-west-2:xxxxxx', + userPoolEndpoint: expectedUserPoolEndpoint, + }, + }, + }); + await resendSignUpCode({ + username: user1.username, + }); + expect(mockCreateCognitoUserPoolEndpointResolver).toHaveBeenCalledWith({ + endpointOverride: expectedUserPoolEndpoint, + }); + }); + it('should throw an error when username is empty', async () => { expect.assertions(2); try { diff --git a/packages/auth/__tests__/providers/cognito/resetPassword.test.ts b/packages/auth/__tests__/providers/cognito/resetPassword.test.ts index 3432ae17c0a..41deeeb170a 100644 --- a/packages/auth/__tests__/providers/cognito/resetPassword.test.ts +++ b/packages/auth/__tests__/providers/cognito/resetPassword.test.ts @@ -6,7 +6,8 @@ import { AuthError } from '../../../src/errors/AuthError'; import { AuthValidationErrorCode } from '../../../src/errors/types/validation'; import { resetPassword } from '../../../src/providers/cognito'; import { ForgotPasswordException } from '../../../src/providers/cognito/types/errors'; -import { forgotPassword } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; +import { createForgotPasswordClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../../../src/providers/cognito/factories'; import { authAPITestParams } from './testUtils/authApiTestParams'; import { getMockError } from './testUtils/data'; @@ -21,12 +22,19 @@ jest.mock('@aws-amplify/core/internals/utils', () => ({ isBrowser: jest.fn(() => false), })); jest.mock( - '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider', + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', ); +jest.mock('../../../src/providers/cognito/factories'); describe('resetPassword', () => { // assert mocks - const mockForgotPassword = forgotPassword as jest.Mock; + const mockForgotPassword = jest.fn(); + const mockCreateForgotPasswordClient = jest.mocked( + createForgotPasswordClient, + ); + const mockCreateCognitoUserPoolEndpointResolver = jest.mocked( + createCognitoUserPoolEndpointResolver, + ); beforeAll(() => { setUpGetConfig(Amplify); @@ -36,10 +44,13 @@ describe('resetPassword', () => { mockForgotPassword.mockResolvedValue( authAPITestParams.resetPasswordHttpCallResult, ); + mockCreateForgotPasswordClient.mockReturnValueOnce(mockForgotPassword); }); afterEach(() => { mockForgotPassword.mockReset(); + mockCreateForgotPasswordClient.mockClear(); + mockCreateCognitoUserPoolEndpointResolver.mockClear(); }); it('should call forgotPassword and return a result', async () => { @@ -47,6 +58,26 @@ describe('resetPassword', () => { expect(result).toEqual(authAPITestParams.resetPasswordResult); }); + it('invokes createCognitoUserPoolEndpointResolver with expected endpointOverride', async () => { + const expectedUserPoolEndpoint = 'https://my-custom-endpoint.com'; + jest.mocked(Amplify.getConfig).mockReturnValueOnce({ + Auth: { + Cognito: { + userPoolClientId: '111111-aaaaa-42d8-891d-ee81a1549398', + userPoolId: 'us-west-2_zzzzz', + identityPoolId: 'us-west-2:xxxxxx', + userPoolEndpoint: expectedUserPoolEndpoint, + }, + }, + }); + + await resetPassword(authAPITestParams.resetPasswordRequest); + + expect(mockCreateCognitoUserPoolEndpointResolver).toHaveBeenCalledWith({ + endpointOverride: expectedUserPoolEndpoint, + }); + }); + it('should contain clientMetadata from request', async () => { await resetPassword({ username: 'username', diff --git a/packages/auth/__tests__/providers/cognito/sendUserAttributeVerificationCode.test.ts b/packages/auth/__tests__/providers/cognito/sendUserAttributeVerificationCode.test.ts index 2b236d1db5a..31376edf642 100644 --- a/packages/auth/__tests__/providers/cognito/sendUserAttributeVerificationCode.test.ts +++ b/packages/auth/__tests__/providers/cognito/sendUserAttributeVerificationCode.test.ts @@ -7,7 +7,8 @@ import { decodeJWT } from '@aws-amplify/core/internals/utils'; import { AuthError } from '../../../src/errors/AuthError'; import { sendUserAttributeVerificationCode } from '../../../src/providers/cognito'; import { GetUserAttributeVerificationException } from '../../../src/providers/cognito/types/errors'; -import { getUserAttributeVerificationCode } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; +import { createGetUserAttributeVerificationCodeClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../../../src/providers/cognito/factories'; import { authAPITestParams } from './testUtils/authApiTestParams'; import { getMockError, mockAccessToken } from './testUtils/data'; @@ -22,14 +23,20 @@ jest.mock('@aws-amplify/core/internals/utils', () => ({ isBrowser: jest.fn(() => false), })); jest.mock( - '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider', + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', ); +jest.mock('../../../src/providers/cognito/factories'); describe('sendUserAttributeVerificationCode', () => { // assert mocks const mockFetchAuthSession = fetchAuthSession as jest.Mock; - const mockGetUserAttributeVerificationCode = - getUserAttributeVerificationCode as jest.Mock; + const mockGetUserAttributeVerificationCode = jest.fn(); + const mockCreateGetUserAttributeVerificationCodeClient = jest.mocked( + createGetUserAttributeVerificationCodeClient, + ); + const mockCreateCognitoUserPoolEndpointResolver = jest.mocked( + createCognitoUserPoolEndpointResolver, + ); beforeAll(() => { setUpGetConfig(Amplify); @@ -42,11 +49,15 @@ describe('sendUserAttributeVerificationCode', () => { mockGetUserAttributeVerificationCode.mockResolvedValue( authAPITestParams.resendSignUpClientResult, ); + mockCreateGetUserAttributeVerificationCodeClient.mockReturnValueOnce( + mockGetUserAttributeVerificationCode, + ); }); afterEach(() => { mockGetUserAttributeVerificationCode.mockReset(); mockFetchAuthSession.mockClear(); + mockCreateGetUserAttributeVerificationCodeClient.mockClear(); }); it('should return a result', async () => { @@ -69,6 +80,30 @@ describe('sendUserAttributeVerificationCode', () => { expect(mockGetUserAttributeVerificationCode).toHaveBeenCalledTimes(1); }); + it('invokes mockCreateCognitoUserPoolEndpointResolver with expected endpointOverride', async () => { + const expectedUserPoolEndpoint = 'https://my-custom-endpoint.com'; + jest.mocked(Amplify.getConfig).mockReturnValueOnce({ + Auth: { + Cognito: { + userPoolClientId: '111111-aaaaa-42d8-891d-ee81a1549398', + userPoolId: 'us-west-2_zzzzz', + identityPoolId: 'us-west-2:xxxxxx', + userPoolEndpoint: expectedUserPoolEndpoint, + }, + }, + }); + await sendUserAttributeVerificationCode({ + userAttributeKey: 'email', + options: { + clientMetadata: { foo: 'bar' }, + }, + }); + + expect(mockCreateCognitoUserPoolEndpointResolver).toHaveBeenCalledWith({ + endpointOverride: expectedUserPoolEndpoint, + }); + }); + it('should throw an error when service returns an error response', async () => { expect.assertions(2); mockGetUserAttributeVerificationCode.mockImplementation(() => { diff --git a/packages/auth/__tests__/providers/cognito/setUpTOTP.test.ts b/packages/auth/__tests__/providers/cognito/setUpTOTP.test.ts index 1f7399093cc..1a7d0cfbc4b 100644 --- a/packages/auth/__tests__/providers/cognito/setUpTOTP.test.ts +++ b/packages/auth/__tests__/providers/cognito/setUpTOTP.test.ts @@ -6,8 +6,9 @@ import { decodeJWT } from '@aws-amplify/core/internals/utils'; import { AuthError } from '../../../src/errors/AuthError'; import { AssociateSoftwareTokenException } from '../../../src/providers/cognito/types/errors'; -import { associateSoftwareToken } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; import { setUpTOTP } from '../../../src/providers/cognito'; +import { createAssociateSoftwareTokenClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../../../src/providers/cognito/factories'; import { getMockError, mockAccessToken } from './testUtils/data'; import { setUpGetConfig } from './testUtils/setUpGetConfig'; @@ -21,14 +22,21 @@ jest.mock('@aws-amplify/core/internals/utils', () => ({ isBrowser: jest.fn(() => false), })); jest.mock( - '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider', + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', ); +jest.mock('../../../src/providers/cognito/factories'); describe('setUpTOTP', () => { const secretCode = 'secret-code'; // assert mocks const mockFetchAuthSession = fetchAuthSession as jest.Mock; - const mockAssociateSoftwareToken = associateSoftwareToken as jest.Mock; + const mockAssociateSoftwareToken = jest.fn(); + const mockCreateAssociateSoftwareTokenClient = jest.mocked( + createAssociateSoftwareTokenClient, + ); + const mockCreateCognitoUserPoolEndpointResolver = jest.mocked( + createCognitoUserPoolEndpointResolver, + ); beforeAll(() => { setUpGetConfig(Amplify); @@ -42,11 +50,15 @@ describe('setUpTOTP', () => { SecretCode: secretCode, $metadata: {}, }); + mockCreateAssociateSoftwareTokenClient.mockReturnValueOnce( + mockAssociateSoftwareToken, + ); }); afterEach(() => { mockAssociateSoftwareToken.mockReset(); mockFetchAuthSession.mockClear(); + mockCreateAssociateSoftwareTokenClient.mockClear(); }); it('setUpTOTP API should call the UserPoolClient and should return a TOTPSetupDetails', async () => { @@ -64,6 +76,26 @@ describe('setUpTOTP', () => { expect(result.getSetupUri('appName', 'amplify')).toBeInstanceOf(URL); }); + it('invokes mockCreateCognitoUserPoolEndpointResolver with expected endpointOverride', async () => { + const expectedUserPoolEndpoint = 'https://my-custom-endpoint.com'; + jest.mocked(Amplify.getConfig).mockReturnValueOnce({ + Auth: { + Cognito: { + userPoolClientId: '111111-aaaaa-42d8-891d-ee81a1549398', + userPoolId: 'us-west-2_zzzzz', + identityPoolId: 'us-west-2:xxxxxx', + userPoolEndpoint: expectedUserPoolEndpoint, + }, + }, + }); + + await setUpTOTP(); + + expect(mockCreateCognitoUserPoolEndpointResolver).toHaveBeenCalledWith({ + endpointOverride: expectedUserPoolEndpoint, + }); + }); + it('should throw an error when service returns an error response', async () => { expect.assertions(2); mockAssociateSoftwareToken.mockImplementation(() => { diff --git a/packages/auth/__tests__/providers/cognito/signInErrorCases.test.ts b/packages/auth/__tests__/providers/cognito/signInErrorCases.test.ts index b4e8453b17d..f66241497f3 100644 --- a/packages/auth/__tests__/providers/cognito/signInErrorCases.test.ts +++ b/packages/auth/__tests__/providers/cognito/signInErrorCases.test.ts @@ -6,9 +6,9 @@ import { Amplify } from '@aws-amplify/core'; import { AuthError } from '../../../src/errors/AuthError'; import { AuthValidationErrorCode } from '../../../src/errors/types/validation'; import { getCurrentUser, signIn } from '../../../src/providers/cognito'; -import { initiateAuth } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; import { InitiateAuthException } from '../../../src/providers/cognito/types/errors'; import { USER_ALREADY_AUTHENTICATED_EXCEPTION } from '../../../src/errors/constants'; +import { createInitiateAuthClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; import { authAPITestParams } from './testUtils/authApiTestParams'; import { getMockError } from './testUtils/data'; @@ -24,18 +24,23 @@ jest.mock('@aws-amplify/core/internals/utils', () => ({ })); jest.mock('../../../src/providers/cognito/apis/getCurrentUser'); jest.mock( - '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider', + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', ); describe('signIn API error path cases:', () => { // assert mocks - const mockInitiateAuth = initiateAuth as jest.Mock; + const mockCreateInitiateAuthClient = jest.mocked(createInitiateAuthClient); + const mockInitiateAuth = jest.fn(); const mockedGetCurrentUser = getCurrentUser as jest.Mock; beforeAll(() => { setUpGetConfig(Amplify); }); + beforeEach(() => { + mockCreateInitiateAuthClient.mockReturnValueOnce(mockInitiateAuth); + }); + afterEach(() => { mockedGetCurrentUser.mockReset(); mockInitiateAuth.mockClear(); diff --git a/packages/auth/__tests__/providers/cognito/signInStateManagement.test.ts b/packages/auth/__tests__/providers/cognito/signInStateManagement.test.ts index dcefb80a121..80006cbf675 100644 --- a/packages/auth/__tests__/providers/cognito/signInStateManagement.test.ts +++ b/packages/auth/__tests__/providers/cognito/signInStateManagement.test.ts @@ -6,8 +6,8 @@ import { Amplify } from '@aws-amplify/core'; import { getCurrentUser, signIn } from '../../../src/providers/cognito'; import * as signInHelpers from '../../../src/providers/cognito/utils/signInHelpers'; import { signInStore } from '../../../src/providers/cognito/utils/signInStore'; -import { RespondToAuthChallengeCommandOutput } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider/types'; import { cognitoUserPoolsTokenProvider } from '../../../src/providers/cognito/tokenProvider'; +import { RespondToAuthChallengeCommandOutput } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider/types'; import { authAPITestParams } from './testUtils/authApiTestParams'; diff --git a/packages/auth/__tests__/providers/cognito/signInWithCustomAuth.test.ts b/packages/auth/__tests__/providers/cognito/signInWithCustomAuth.test.ts index 87828e427f8..c9e5ec7ab68 100644 --- a/packages/auth/__tests__/providers/cognito/signInWithCustomAuth.test.ts +++ b/packages/auth/__tests__/providers/cognito/signInWithCustomAuth.test.ts @@ -6,12 +6,12 @@ import { Amplify } from 'aws-amplify'; import { signIn } from '../../../src/providers/cognito'; import { signInWithCustomAuth } from '../../../src/providers/cognito/apis/signInWithCustomAuth'; import * as initiateAuthHelpers from '../../../src/providers/cognito/utils/signInHelpers'; -import { InitiateAuthCommandOutput } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider/types'; import { cognitoUserPoolsTokenProvider, tokenOrchestrator, } from '../../../src/providers/cognito/tokenProvider'; -import * as clients from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; +import { createInitiateAuthClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { InitiateAuthCommandOutput } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider/types'; import { authAPITestParams } from './testUtils/authApiTestParams'; @@ -19,6 +19,9 @@ jest.mock('@aws-amplify/core/internals/utils', () => ({ ...jest.requireActual('@aws-amplify/core/internals/utils'), isBrowser: jest.fn(() => false), })); +jest.mock( + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', +); const authConfig = { Cognito: { @@ -85,25 +88,23 @@ describe('signIn API happy path cases', () => { }); describe('Cognito ASF', () => { - let initiateAuthSpy: jest.SpyInstance; + const mockInitiateAuth = jest.fn(); + const mockCreateInitiateAuthClient = jest.mocked(createInitiateAuthClient); afterAll(() => { jest.restoreAllMocks(); }); beforeEach(() => { - initiateAuthSpy = jest - .spyOn(clients, 'initiateAuth') - .mockImplementationOnce( - async (): Promise => ({ - ChallengeName: 'SMS_MFA', - Session: '1234234232', - $metadata: {}, - ChallengeParameters: { - CODE_DELIVERY_DELIVERY_MEDIUM: 'SMS', - CODE_DELIVERY_DESTINATION: '*******9878', - }, - }), - ); + mockInitiateAuth.mockResolvedValueOnce({ + ChallengeName: 'SMS_MFA', + Session: '1234234232', + $metadata: {}, + ChallengeParameters: { + CODE_DELIVERY_DELIVERY_MEDIUM: 'SMS', + CODE_DELIVERY_DESTINATION: '*******9878', + }, + }); + mockCreateInitiateAuthClient.mockReturnValueOnce(mockInitiateAuth); // load Cognito ASF polyfill (window as any).AmazonCognitoAdvancedSecurityData = { getData() { @@ -113,7 +114,7 @@ describe('Cognito ASF', () => { }); afterEach(() => { - initiateAuthSpy.mockClear(); + mockInitiateAuth.mockClear(); (window as any).AmazonCognitoAdvancedSecurityData = undefined; }); @@ -124,7 +125,7 @@ describe('Cognito ASF', () => { authFlowType: 'CUSTOM_WITHOUT_SRP', }, }); - expect(initiateAuthSpy).toHaveBeenCalledWith( + expect(mockInitiateAuth).toHaveBeenCalledWith( expect.objectContaining({ region: 'us-west-2', }), diff --git a/packages/auth/__tests__/providers/cognito/signInWithCustomSRPAuth.test.ts b/packages/auth/__tests__/providers/cognito/signInWithCustomSRPAuth.test.ts index 108e928d683..5d6aa8a1740 100644 --- a/packages/auth/__tests__/providers/cognito/signInWithCustomSRPAuth.test.ts +++ b/packages/auth/__tests__/providers/cognito/signInWithCustomSRPAuth.test.ts @@ -6,12 +6,12 @@ import { Amplify } from 'aws-amplify'; import { signIn } from '../../../src/providers/cognito'; import * as initiateAuthHelpers from '../../../src/providers/cognito/utils/signInHelpers'; import { signInWithCustomSRPAuth } from '../../../src/providers/cognito/apis/signInWithCustomSRPAuth'; -import { RespondToAuthChallengeCommandOutput } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider/types'; import { cognitoUserPoolsTokenProvider, tokenOrchestrator, } from '../../../src/providers/cognito/tokenProvider'; -import * as clients from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; +import { createInitiateAuthClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { RespondToAuthChallengeCommandOutput } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider/types'; import { authAPITestParams } from './testUtils/authApiTestParams'; @@ -20,6 +20,10 @@ jest.mock('@aws-amplify/core/internals/utils', () => ({ isBrowser: jest.fn(() => false), })); +jest.mock( + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', +); + const authConfig = { Cognito: { userPoolClientId: '111111-aaaaa-42d8-891d-ee81a1549398', @@ -92,22 +96,23 @@ describe('signIn API happy path cases', () => { }); describe('Cognito ASF', () => { - let initiateAuthSpy: jest.SpyInstance; + const mockInitiateAuth = jest.fn(); + const mockCreateInitiateAuthClient = jest.mocked(createInitiateAuthClient); afterAll(() => { jest.restoreAllMocks(); }); beforeEach(() => { - initiateAuthSpy = jest - .spyOn(clients, 'initiateAuth') - .mockImplementationOnce(async () => ({ - ChallengeName: 'SRP_AUTH', - Session: '1234234232', - $metadata: {}, - ChallengeParameters: { - USER_ID_FOR_SRP: authAPITestParams.user1.username, - }, - })); + mockInitiateAuth.mockResolvedValueOnce({ + ChallengeName: 'SRP_AUTH', + Session: '1234234232', + $metadata: {}, + ChallengeParameters: { + USER_ID_FOR_SRP: authAPITestParams.user1.username, + }, + }); + mockCreateInitiateAuthClient.mockReturnValueOnce(mockInitiateAuth); + // load Cognito ASF polyfill (window as any).AmazonCognitoAdvancedSecurityData = { getData() { @@ -117,7 +122,8 @@ describe('Cognito ASF', () => { }); afterEach(() => { - initiateAuthSpy.mockClear(); + mockInitiateAuth.mockClear(); + mockCreateInitiateAuthClient.mockClear(); (window as any).AmazonCognitoAdvancedSecurityData = undefined; }); @@ -133,7 +139,7 @@ describe('Cognito ASF', () => { } catch (_) { // only want to test the contents } - expect(initiateAuthSpy).toHaveBeenCalledWith( + expect(mockInitiateAuth).toHaveBeenCalledWith( expect.objectContaining({ region: 'us-west-2', }), diff --git a/packages/auth/__tests__/providers/cognito/signInWithSRP.test.ts b/packages/auth/__tests__/providers/cognito/signInWithSRP.test.ts index c43e773f1d7..36c8d3c118a 100644 --- a/packages/auth/__tests__/providers/cognito/signInWithSRP.test.ts +++ b/packages/auth/__tests__/providers/cognito/signInWithSRP.test.ts @@ -6,14 +6,17 @@ import { Amplify } from 'aws-amplify'; import { signIn } from '../../../src/providers/cognito'; import { signInWithSRP } from '../../../src/providers/cognito/apis/signInWithSRP'; import * as initiateAuthHelpers from '../../../src/providers/cognito/utils/signInHelpers'; -import { RespondToAuthChallengeCommandOutput } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider/types'; import { cognitoUserPoolsTokenProvider, tokenOrchestrator, } from '../../../src/providers/cognito/tokenProvider'; import { AuthError } from '../../../src'; import { createKeysForAuthStorage } from '../../../src/providers/cognito/tokenProvider/TokenStore'; -import * as clients from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; +import { + createInitiateAuthClient, + createRespondToAuthChallengeClient, +} from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { RespondToAuthChallengeCommandOutput } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider/types'; import { authAPITestParams } from './testUtils/authApiTestParams'; @@ -33,6 +36,9 @@ jest.mock('@aws-amplify/core/internals/utils', () => ({ ...jest.requireActual('@aws-amplify/core/internals/utils'), isBrowser: jest.fn(() => false), })); +jest.mock( + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', +); const authConfig = { Cognito: { @@ -193,15 +199,17 @@ describe('signIn API happy path cases', () => { }); describe('sign in with device keys', () => { - const initiateAuthSpy = jest.spyOn(clients, 'initiateAuth'); - const respondToAuthChallengeAuthSpy = jest.spyOn( - clients, - 'respondToAuthChallenge', + const mockInitiateAuth = jest.fn(); + const mockCreateInitiateAuthClient = jest.mocked(createInitiateAuthClient); + const mockRespondToAuthChallenge = jest.fn(); + const mockCreateRespondToAuthChallengeClient = jest.mocked( + createRespondToAuthChallengeClient, ); + beforeEach(() => { setDeviceKeys(); handleUserSRPAuthflowSpy.mockRestore(); - initiateAuthSpy.mockResolvedValueOnce({ + mockInitiateAuth.mockResolvedValueOnce({ ChallengeName: 'SRP_AUTH', Session: '1234234232', $metadata: {}, @@ -209,14 +217,20 @@ describe('signIn API happy path cases', () => { USER_ID_FOR_SRP: lastAuthUser, }, }); - respondToAuthChallengeAuthSpy.mockResolvedValueOnce( + mockCreateInitiateAuthClient.mockReturnValueOnce(mockInitiateAuth); + mockRespondToAuthChallenge.mockResolvedValueOnce( authAPITestParams.RespondToAuthChallengeCommandOutput, ); + mockCreateRespondToAuthChallengeClient.mockReturnValueOnce( + mockRespondToAuthChallenge, + ); }); afterEach(() => { - initiateAuthSpy.mockClear(); - respondToAuthChallengeAuthSpy.mockClear(); + mockInitiateAuth.mockClear(); + mockCreateInitiateAuthClient.mockClear(); + mockRespondToAuthChallenge.mockClear(); + mockCreateRespondToAuthChallengeClient.mockClear(); }); test('respondToAuthChallenge should include device key in the request', async () => { @@ -225,9 +239,9 @@ describe('signIn API happy path cases', () => { password: 'XXXXXXXX', }); - expect(respondToAuthChallengeAuthSpy).toHaveBeenCalledTimes(1); + expect(mockRespondToAuthChallenge).toHaveBeenCalledTimes(1); const deviceKeyFromRequest = - respondToAuthChallengeAuthSpy.mock.calls[0][1].ChallengeResponses + mockRespondToAuthChallenge.mock.calls[0][1].ChallengeResponses ?.DEVICE_KEY; expect(deviceKeyFromRequest).toBe('mockedKey'); }); @@ -245,9 +259,9 @@ describe('signIn API happy path cases', () => { password: 'XXXXXXXX', }); - expect(respondToAuthChallengeAuthSpy).toHaveBeenCalledTimes(1); + expect(mockRespondToAuthChallenge).toHaveBeenCalledTimes(1); const deviceKeyFromRequest = - respondToAuthChallengeAuthSpy.mock.calls[0][1].ChallengeResponses + mockRespondToAuthChallenge.mock.calls[0][1].ChallengeResponses ?.DEVICE_KEY; expect(deviceKeyFromRequest).toBe(undefined); }, @@ -256,22 +270,23 @@ describe('signIn API happy path cases', () => { }); describe('Cognito ASF', () => { - let initiateAuthSpy: jest.SpyInstance; + const mockInitiateAuth = jest.fn(); + const mockCreateInitiateAuthClient = jest.mocked(createInitiateAuthClient); beforeAll(() => { jest.restoreAllMocks(); }); + beforeEach(() => { - initiateAuthSpy = jest - .spyOn(clients, 'initiateAuth') - .mockImplementationOnce(async () => ({ - ChallengeName: 'SRP_AUTH', - Session: '1234234232', - $metadata: {}, - ChallengeParameters: { - USER_ID_FOR_SRP: authAPITestParams.user1.username, - }, - })); + mockInitiateAuth.mockResolvedValueOnce({ + ChallengeName: 'SRP_AUTH', + Session: '1234234232', + $metadata: {}, + ChallengeParameters: { + USER_ID_FOR_SRP: authAPITestParams.user1.username, + }, + }); + mockCreateInitiateAuthClient.mockReturnValueOnce(mockInitiateAuth); // load Cognito ASF polyfill (window as any).AmazonCognitoAdvancedSecurityData = { getData() { @@ -281,7 +296,8 @@ describe('Cognito ASF', () => { }); afterEach(() => { - initiateAuthSpy.mockClear(); + mockInitiateAuth.mockClear(); + mockCreateInitiateAuthClient.mockClear(); (window as any).AmazonCognitoAdvancedSecurityData = undefined; }); @@ -294,7 +310,7 @@ describe('Cognito ASF', () => { } catch (_) { // only want to test the contents } - expect(initiateAuthSpy).toHaveBeenCalledWith( + expect(mockInitiateAuth).toHaveBeenCalledWith( expect.objectContaining({ region: 'us-west-2', }), diff --git a/packages/auth/__tests__/providers/cognito/signInWithUserPassword.test.ts b/packages/auth/__tests__/providers/cognito/signInWithUserPassword.test.ts index 83f3a7d2813..d675ace40a2 100644 --- a/packages/auth/__tests__/providers/cognito/signInWithUserPassword.test.ts +++ b/packages/auth/__tests__/providers/cognito/signInWithUserPassword.test.ts @@ -6,12 +6,12 @@ import { Amplify } from 'aws-amplify'; import { signIn } from '../../../src/providers/cognito'; import * as initiateAuthHelpers from '../../../src/providers/cognito/utils/signInHelpers'; import { signInWithUserPassword } from '../../../src/providers/cognito/apis/signInWithUserPassword'; -import { RespondToAuthChallengeCommandOutput } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider/types'; import { cognitoUserPoolsTokenProvider, tokenOrchestrator, } from '../../../src/providers/cognito/tokenProvider'; -import * as clients from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; +import { createInitiateAuthClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { RespondToAuthChallengeCommandOutput } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider/types'; import { authAPITestParams } from './testUtils/authApiTestParams'; @@ -20,21 +20,28 @@ jest.mock('@aws-amplify/core/internals/utils', () => ({ ...jest.requireActual('@aws-amplify/core/internals/utils'), isBrowser: jest.fn(() => false), })); +jest.mock( + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', +); const authConfig = { Cognito: { userPoolClientId: '111111-aaaaa-42d8-891d-ee81a1549398', userPoolId: 'us-west-2_zzzzz', + userPoolEndpoint: 'https://custom-endpoint.com', }, }; -cognitoUserPoolsTokenProvider.setAuthConfig(authConfig); -Amplify.configure({ - Auth: authConfig, -}); describe('signIn API happy path cases', () => { let handleUserPasswordFlowSpy: jest.SpyInstance; + beforeAll(() => { + Amplify.configure({ + Auth: authConfig, + }); + cognitoUserPoolsTokenProvider.setAuthConfig(authConfig); + }); + beforeEach(() => { handleUserPasswordFlowSpy = jest .spyOn(initiateAuthHelpers, 'handleUserPasswordAuthFlow') @@ -60,7 +67,7 @@ describe('signIn API happy path cases', () => { expect(handleUserPasswordFlowSpy).toHaveBeenCalledTimes(1); }); - test('handleUserPasswordAuthFlow should be called with clientMetada from request', async () => { + test('handleUserPasswordAuthFlow should be called with clientMetadata from request', async () => { const { username } = authAPITestParams.user1; const { password } = authAPITestParams.user1; await signInWithUserPassword({ @@ -79,22 +86,19 @@ describe('signIn API happy path cases', () => { }); describe('Cognito ASF', () => { - let initiateAuthSpy: jest.SpyInstance; + const mockInitiateAuth = jest.fn(); + const mockCreateInitiateAuthClient = jest.mocked(createInitiateAuthClient); - afterAll(() => { - jest.restoreAllMocks(); - }); beforeEach(() => { - initiateAuthSpy = jest - .spyOn(clients, 'initiateAuth') - .mockImplementationOnce(async () => ({ - ChallengeName: 'SRP_AUTH', - Session: '1234234232', - $metadata: {}, - ChallengeParameters: { - USER_ID_FOR_SRP: authAPITestParams.user1.username, - }, - })); + mockInitiateAuth.mockResolvedValueOnce({ + ChallengeName: 'SRP_AUTH', + Session: '1234234232', + $metadata: {}, + ChallengeParameters: { + USER_ID_FOR_SRP: authAPITestParams.user1.username, + }, + }); + mockCreateInitiateAuthClient.mockReturnValueOnce(mockInitiateAuth); // load Cognito ASF polyfill (window as any).AmazonCognitoAdvancedSecurityData = { getData() { @@ -104,7 +108,8 @@ describe('Cognito ASF', () => { }); afterEach(() => { - initiateAuthSpy.mockClear(); + mockInitiateAuth.mockClear(); + mockCreateInitiateAuthClient.mockClear(); (window as any).AmazonCognitoAdvancedSecurityData = undefined; }); @@ -120,7 +125,7 @@ describe('Cognito ASF', () => { } catch (_) { // only want to test the contents } - expect(initiateAuthSpy).toHaveBeenCalledWith( + expect(mockInitiateAuth).toHaveBeenCalledWith( expect.objectContaining({ region: 'us-west-2', }), diff --git a/packages/auth/__tests__/providers/cognito/signOut.test.ts b/packages/auth/__tests__/providers/cognito/signOut.test.ts index 4992b4a3a5c..49779a748ca 100644 --- a/packages/auth/__tests__/providers/cognito/signOut.test.ts +++ b/packages/auth/__tests__/providers/cognito/signOut.test.ts @@ -11,26 +11,26 @@ import { AMPLIFY_SYMBOL } from '@aws-amplify/core/internals/utils'; import { signOut } from '../../../src/providers/cognito/apis/signOut'; import { tokenOrchestrator } from '../../../src/providers/cognito/tokenProvider'; -import { - globalSignOut, - revokeToken, -} from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; -import { getRegion } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider/utils'; import { DefaultOAuthStore } from '../../../src/providers/cognito/utils/signInWithRedirectStore'; import { handleOAuthSignOut } from '../../../src/providers/cognito/utils/oauth'; import { AuthTokenStore } from '../../../src/providers/cognito/tokenProvider/types'; +import { + createGlobalSignOutClient, + createRevokeTokenClient, +} from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { getRegionFromUserPoolId } from '../../../src/foundation/parsers'; +import { createCognitoUserPoolEndpointResolver } from '../../../src/providers/cognito/factories'; jest.mock('@aws-amplify/core'); jest.mock('../../../src/providers/cognito/tokenProvider'); -jest.mock( - '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider', -); -jest.mock( - '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider/utils', -); jest.mock('../../../src/providers/cognito/utils/oauth'); jest.mock('../../../src/providers/cognito/utils/signInWithRedirectStore'); jest.mock('../../../src/utils'); +jest.mock( + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', +); +jest.mock('../../../src/foundation/parsers'); +jest.mock('../../../src/providers/cognito/factories'); describe('signOut', () => { // eslint-disable-next-line camelcase @@ -54,15 +54,20 @@ describe('signOut', () => { // assert mocks const mockAmplify = Amplify as jest.Mocked; const mockClearCredentials = clearCredentials as jest.Mock; - const mockGetRegion = getRegion as jest.Mock; - const mockGlobalSignOut = globalSignOut as jest.Mock; + const mockGetRegionFromUserPoolId = jest.mocked(getRegionFromUserPoolId); + const mockGlobalSignOut = jest.fn(); + const mockCreateGlobalSignOutClient = jest.mocked(createGlobalSignOutClient); const mockHandleOAuthSignOut = handleOAuthSignOut as jest.Mock; const mockHub = Hub as jest.Mocked; - const mockRevokeToken = revokeToken as jest.Mock; + const mockRevokeToken = jest.fn(); + const mockedRevokeTokenClient = jest.mocked(createRevokeTokenClient); const mockTokenOrchestrator = tokenOrchestrator as jest.Mocked< typeof tokenOrchestrator >; const MockDefaultOAuthStore = DefaultOAuthStore as jest.Mock; + const mockCreateCognitoUserPoolEndpointResolver = jest.mocked( + createCognitoUserPoolEndpointResolver, + ); // create mocks const mockLoadTokens = jest.fn(); const mockAuthTokenStore = { @@ -95,7 +100,7 @@ describe('signOut', () => { }); beforeAll(() => { - mockGetRegion.mockReturnValue(region); + mockGetRegionFromUserPoolId.mockReturnValue(region); MockDefaultOAuthStore.mockImplementation( () => mockDefaultOAuthStoreInstance, ); @@ -104,7 +109,9 @@ describe('signOut', () => { beforeEach(() => { mockAmplify.getConfig.mockReturnValue({ Auth: { Cognito: cognitoConfig } }); mockGlobalSignOut.mockResolvedValue({ $metadata: {} }); + mockCreateGlobalSignOutClient.mockReturnValueOnce(mockGlobalSignOut); mockRevokeToken.mockResolvedValue({}); + mockedRevokeTokenClient.mockReturnValueOnce(mockRevokeToken); mockTokenOrchestrator.getTokenStore.mockReturnValue(mockAuthTokenStore); mockLoadTokens.mockResolvedValue(cognitoAuthTokens); }); @@ -114,10 +121,11 @@ describe('signOut', () => { mockGlobalSignOut.mockReset(); mockRevokeToken.mockReset(); mockClearCredentials.mockClear(); - mockGetRegion.mockClear(); + mockGetRegionFromUserPoolId.mockClear(); mockHub.dispatch.mockClear(); mockTokenOrchestrator.clearTokens.mockClear(); loggerDebugSpy.mockClear(); + mockCreateCognitoUserPoolEndpointResolver.mockClear(); }); describe('Without OAuth configured', () => { @@ -128,11 +136,36 @@ describe('signOut', () => { { region }, { ClientId: cognitoConfig.userPoolClientId, Token: refreshToken }, ); - expect(mockGetRegion).toHaveBeenCalledTimes(1); + expect(mockGetRegionFromUserPoolId).toHaveBeenCalledTimes(1); expect(mockGlobalSignOut).not.toHaveBeenCalled(); expectSignOut().toComplete(); }); + it('invokes createCognitoUserPoolEndpointResolver with the userPoolEndpoint for creating the revokeToken client', async () => { + const expectedUserPoolEndpoint = 'https://my-custom-endpoint.com'; + const expectedEndpointResolver = jest.fn(); + mockAmplify.getConfig.mockReturnValueOnce({ + Auth: { + Cognito: { + ...cognitoConfig, + userPoolEndpoint: expectedUserPoolEndpoint, + }, + }, + }); + mockCreateCognitoUserPoolEndpointResolver.mockReturnValueOnce( + expectedEndpointResolver, + ); + + await signOut(); + + expect(mockCreateCognitoUserPoolEndpointResolver).toHaveBeenCalledWith({ + endpointOverride: expectedUserPoolEndpoint, + }); + expect(mockedRevokeTokenClient).toHaveBeenCalledWith({ + endpointResolver: expectedEndpointResolver, + }); + }); + it('should perform client sign out on an irrevocable session', async () => { mockLoadTokens.mockResolvedValue({ ...cognitoAuthTokens, @@ -143,7 +176,7 @@ describe('signOut', () => { expect(mockRevokeToken).not.toHaveBeenCalled(); expect(mockGlobalSignOut).not.toHaveBeenCalled(); - expect(mockGetRegion).not.toHaveBeenCalled(); + expect(mockGetRegionFromUserPoolId).not.toHaveBeenCalled(); expectSignOut().toComplete(); }); @@ -154,11 +187,36 @@ describe('signOut', () => { { region: 'us-west-2' }, { AccessToken: accessToken.toString() }, ); - expect(mockGetRegion).toHaveBeenCalledTimes(1); + expect(mockGetRegionFromUserPoolId).toHaveBeenCalledTimes(1); expect(mockRevokeToken).not.toHaveBeenCalled(); expectSignOut().toComplete(); }); + it('invokes createCognitoUserPoolEndpointResolver with the userPoolEndpoint for creating the globalSignOut client', async () => { + const expectedUserPoolEndpoint = 'https://my-custom-endpoint.com'; + const expectedEndpointResolver = jest.fn(); + mockAmplify.getConfig.mockReturnValueOnce({ + Auth: { + Cognito: { + ...cognitoConfig, + userPoolEndpoint: expectedUserPoolEndpoint, + }, + }, + }); + mockCreateCognitoUserPoolEndpointResolver.mockReturnValueOnce( + expectedEndpointResolver, + ); + + await signOut({ global: true }); + + expect(mockCreateCognitoUserPoolEndpointResolver).toHaveBeenCalledWith({ + endpointOverride: expectedUserPoolEndpoint, + }); + expect(mockCreateGlobalSignOutClient).toHaveBeenCalledWith({ + endpointResolver: expectedEndpointResolver, + }); + }); + it('should still perform client sign out if token revoke fails', async () => { mockRevokeToken.mockRejectedValue(new Error()); @@ -167,7 +225,7 @@ describe('signOut', () => { expect(loggerDebugSpy).toHaveBeenCalledWith( expect.stringContaining('Client signOut error caught'), ); - expect(mockGetRegion).toHaveBeenCalledTimes(1); + expect(mockGetRegionFromUserPoolId).toHaveBeenCalledTimes(1); expectSignOut().toComplete(); }); @@ -179,7 +237,7 @@ describe('signOut', () => { expect(loggerDebugSpy).toHaveBeenCalledWith( expect.stringContaining('Global signOut error caught'), ); - expect(mockGetRegion).toHaveBeenCalledTimes(1); + expect(mockGetRegionFromUserPoolId).toHaveBeenCalledTimes(1); expectSignOut().toComplete(); }); }); diff --git a/packages/auth/__tests__/providers/cognito/signUp.test.ts b/packages/auth/__tests__/providers/cognito/signUp.test.ts index 87e0dda27c6..cb2b9b84d64 100644 --- a/packages/auth/__tests__/providers/cognito/signUp.test.ts +++ b/packages/auth/__tests__/providers/cognito/signUp.test.ts @@ -4,10 +4,11 @@ import { Amplify } from '@aws-amplify/core'; import { signUp } from '../../../src/providers/cognito'; -import { signUp as providerSignUp } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; import { AuthValidationErrorCode } from '../../../src/errors/types/validation'; import { AuthError } from '../../../src/errors/AuthError'; import { SignUpException } from '../../../src/providers/cognito/types/errors'; +import { createSignUpClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../../../src/providers/cognito/factories'; import { authAPITestParams } from './testUtils/authApiTestParams'; import { getMockError } from './testUtils/data'; @@ -21,21 +22,35 @@ jest.mock('@aws-amplify/core/internals/utils', () => ({ ...jest.requireActual('@aws-amplify/core/internals/utils'), isBrowser: jest.fn(() => false), })); + jest.mock( - '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider', + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', ); - -const userId = '1234567890'; +jest.mock('../../../src/providers/cognito/factories'); describe('signUp', () => { + const userId = '1234567890'; const { user1 } = authAPITestParams; // assert mocks - const mockSignUp = providerSignUp as jest.Mock; + const mockSignUp = jest.fn(); + const mockCreateSignUpClient = jest.mocked(createSignUpClient); + const mockCreateCognitoUserPoolEndpointResolver = jest.mocked( + createCognitoUserPoolEndpointResolver, + ); beforeAll(() => { setUpGetConfig(Amplify); }); + beforeEach(() => { + mockCreateSignUpClient.mockReturnValueOnce(mockSignUp); + }); + + afterEach(() => { + mockCreateSignUpClient.mockClear(); + mockCreateCognitoUserPoolEndpointResolver.mockClear(); + }); + describe('Happy Path Cases:', () => { beforeEach(() => { mockSignUp.mockResolvedValue(authAPITestParams.signUpHttpCallResult); @@ -70,6 +85,31 @@ describe('signUp', () => { expect(mockSignUp).toHaveBeenCalledTimes(1); }); + it('invokes mockCreateCognitoUserPoolEndpointResolver with expected endpointOverride', async () => { + const expectedUserPoolEndpoint = 'https://my-custom-endpoint.com'; + jest.mocked(Amplify.getConfig).mockReturnValueOnce({ + Auth: { + Cognito: { + userPoolClientId: '111111-aaaaa-42d8-891d-ee81a1549398', + userPoolId: 'us-west-2_zzzzz', + identityPoolId: 'us-west-2:xxxxxx', + userPoolEndpoint: expectedUserPoolEndpoint, + }, + }, + }); + await signUp({ + username: user1.username, + password: user1.password, + options: { + userAttributes: { email: user1.email }, + }, + }); + + expect(mockCreateCognitoUserPoolEndpointResolver).toHaveBeenCalledWith({ + endpointOverride: expectedUserPoolEndpoint, + }); + }); + it('should return `CONFIRM_SIGN_UP` step when user isn`t confirmed yet', async () => { const result = await signUp({ username: user1.username, diff --git a/packages/auth/__tests__/providers/cognito/updateMFAPreference.test.ts b/packages/auth/__tests__/providers/cognito/updateMFAPreference.test.ts index dbaeca398f6..a9d4d6c9e65 100644 --- a/packages/auth/__tests__/providers/cognito/updateMFAPreference.test.ts +++ b/packages/auth/__tests__/providers/cognito/updateMFAPreference.test.ts @@ -8,10 +8,11 @@ import { UpdateMFAPreferenceInput, updateMFAPreference, } from '../../../src/providers/cognito'; -import { setUserMFAPreference } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; import { AuthError } from '../../../src/errors/AuthError'; import { SetUserMFAPreferenceException } from '../../../src/providers/cognito/types/errors'; import { getMFASettings } from '../../../src/providers/cognito/apis/updateMFAPreference'; +import { createSetUserMFAPreferenceClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../../../src/providers/cognito/factories'; import { getMockError, mockAccessToken } from './testUtils/data'; import { setUpGetConfig } from './testUtils/setUpGetConfig'; @@ -25,8 +26,9 @@ jest.mock('@aws-amplify/core/internals/utils', () => ({ isBrowser: jest.fn(() => false), })); jest.mock( - '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider', + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', ); +jest.mock('../../../src/providers/cognito/factories'); const mfaChoices: UpdateMFAPreferenceInput[] = [ { sms: 'DISABLED', totp: 'DISABLED' }, @@ -51,7 +53,13 @@ const mfaChoices: UpdateMFAPreferenceInput[] = [ describe('updateMFAPreference', () => { // assert mocks const mockFetchAuthSession = fetchAuthSession as jest.Mock; - const mockSetUserMFAPreference = setUserMFAPreference as jest.Mock; + const mockSetUserMFAPreference = jest.fn(); + const mockCreateSetUserMFAPreferenceClient = jest.mocked( + createSetUserMFAPreferenceClient, + ); + const mockCreateCognitoUserPoolEndpointResolver = jest.mocked( + createCognitoUserPoolEndpointResolver, + ); beforeAll(() => { setUpGetConfig(Amplify); @@ -62,11 +70,15 @@ describe('updateMFAPreference', () => { beforeEach(() => { mockSetUserMFAPreference.mockResolvedValue({}); + mockCreateSetUserMFAPreferenceClient.mockReturnValueOnce( + mockSetUserMFAPreference, + ); }); afterEach(() => { mockSetUserMFAPreference.mockReset(); mockFetchAuthSession.mockClear(); + mockCreateSetUserMFAPreferenceClient.mockClear(); }); it.each(mfaChoices)( @@ -88,6 +100,25 @@ describe('updateMFAPreference', () => { }, ); + it('invokes mockCreateCognitoUserPoolEndpointResolver with expected endpointOverride', async () => { + const expectedUserPoolEndpoint = 'https://my-custom-endpoint.com'; + jest.mocked(Amplify.getConfig).mockReturnValueOnce({ + Auth: { + Cognito: { + userPoolClientId: '111111-aaaaa-42d8-891d-ee81a1549398', + userPoolId: 'us-west-2_zzzzz', + identityPoolId: 'us-west-2:xxxxxx', + userPoolEndpoint: expectedUserPoolEndpoint, + }, + }, + }); + await updateMFAPreference(mfaChoices[0]); + + expect(mockCreateCognitoUserPoolEndpointResolver).toHaveBeenCalledWith({ + endpointOverride: expectedUserPoolEndpoint, + }); + }); + it('should throw an error when service returns an error response', async () => { expect.assertions(2); mockSetUserMFAPreference.mockImplementation(() => { diff --git a/packages/auth/__tests__/providers/cognito/updatePassword.test.ts b/packages/auth/__tests__/providers/cognito/updatePassword.test.ts index 42c0869a9a3..72dfe80119e 100644 --- a/packages/auth/__tests__/providers/cognito/updatePassword.test.ts +++ b/packages/auth/__tests__/providers/cognito/updatePassword.test.ts @@ -8,7 +8,8 @@ import { AuthError } from '../../../src/errors/AuthError'; import { AuthValidationErrorCode } from '../../../src/errors/types/validation'; import { updatePassword } from '../../../src/providers/cognito'; import { ChangePasswordException } from '../../../src/providers/cognito/types/errors'; -import { changePassword } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; +import { createChangePasswordClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../../../src/providers/cognito/factories'; import { getMockError, mockAccessToken } from './testUtils/data'; import { setUpGetConfig } from './testUtils/setUpGetConfig'; @@ -22,15 +23,22 @@ jest.mock('@aws-amplify/core/internals/utils', () => ({ isBrowser: jest.fn(() => false), })); jest.mock( - '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider', + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', ); +jest.mock('../../../src/providers/cognito/factories'); describe('updatePassword', () => { const oldPassword = 'oldPassword'; const newPassword = 'newPassword'; // assert mocks const mockFetchAuthSession = fetchAuthSession as jest.Mock; - const mockChangePassword = changePassword as jest.Mock; + const mockChangePassword = jest.fn(); + const mockCreateChangePasswordClient = jest.mocked( + createChangePasswordClient, + ); + const mockCreateCognitoUserPoolEndpointResolver = jest.mocked( + createCognitoUserPoolEndpointResolver, + ); beforeAll(() => { setUpGetConfig(Amplify); @@ -41,11 +49,13 @@ describe('updatePassword', () => { beforeEach(() => { mockChangePassword.mockResolvedValue({}); + mockCreateChangePasswordClient.mockReturnValueOnce(mockChangePassword); }); afterEach(() => { mockChangePassword.mockReset(); mockFetchAuthSession.mockClear(); + mockCreateChangePasswordClient.mockClear(); }); it('should call changePassword', async () => { @@ -61,6 +71,25 @@ describe('updatePassword', () => { ); }); + it('invokes mockCreateCognitoUserPoolEndpointResolver with expected endpointOverride', async () => { + const expectedUserPoolEndpoint = 'https://my-custom-endpoint.com'; + jest.mocked(Amplify.getConfig).mockReturnValueOnce({ + Auth: { + Cognito: { + userPoolClientId: '111111-aaaaa-42d8-891d-ee81a1549398', + userPoolId: 'us-west-2_zzzzz', + identityPoolId: 'us-west-2:xxxxxx', + userPoolEndpoint: expectedUserPoolEndpoint, + }, + }, + }); + await updatePassword({ oldPassword, newPassword }); + + expect(mockCreateCognitoUserPoolEndpointResolver).toHaveBeenCalledWith({ + endpointOverride: expectedUserPoolEndpoint, + }); + }); + it('should throw an error when oldPassword is empty', async () => { expect.assertions(2); try { diff --git a/packages/auth/__tests__/providers/cognito/updateUserAttributes.test.ts b/packages/auth/__tests__/providers/cognito/updateUserAttributes.test.ts index 3b1ca0f9d99..bfa9643b76d 100644 --- a/packages/auth/__tests__/providers/cognito/updateUserAttributes.test.ts +++ b/packages/auth/__tests__/providers/cognito/updateUserAttributes.test.ts @@ -7,8 +7,9 @@ import { decodeJWT } from '@aws-amplify/core/internals/utils'; import { AuthError } from '../../../src/errors/AuthError'; import { updateUserAttributes } from '../../../src/providers/cognito'; import { UpdateUserAttributesException } from '../../../src/providers/cognito/types/errors'; -import { updateUserAttributes as providerUpdateUserAttributes } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; import { toAttributeType } from '../../../src/providers/cognito/utils/apiHelpers'; +import { createUpdateUserAttributesClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../../../src/providers/cognito/factories'; import { getMockError, mockAccessToken } from './testUtils/data'; import { setUpGetConfig } from './testUtils/setUpGetConfig'; @@ -22,13 +23,20 @@ jest.mock('@aws-amplify/core/internals/utils', () => ({ isBrowser: jest.fn(() => false), })); jest.mock( - '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider', + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', ); +jest.mock('../../../src/providers/cognito/factories'); describe('updateUserAttributes', () => { // assert mocks const mockFetchAuthSession = fetchAuthSession as jest.Mock; - const mockUpdateUserAttributes = providerUpdateUserAttributes as jest.Mock; + const mockUpdateUserAttributes = jest.fn(); + const mockCreateUpdateUserAttributesClient = jest.mocked( + createUpdateUserAttributesClient, + ); + const mockCreateCognitoUserPoolEndpointResolver = jest.mocked( + createCognitoUserPoolEndpointResolver, + ); beforeAll(() => { setUpGetConfig(Amplify); @@ -52,11 +60,15 @@ describe('updateUserAttributes', () => { }, ], }); + mockCreateUpdateUserAttributesClient.mockReturnValueOnce( + mockUpdateUserAttributes, + ); }); afterEach(() => { mockUpdateUserAttributes.mockReset(); mockFetchAuthSession.mockClear(); + mockCreateUpdateUserAttributesClient.mockClear(); }); it('should return a map with updated and not updated attributes', async () => { @@ -121,6 +133,30 @@ describe('updateUserAttributes', () => { ); }); + it('invokes mockCreateCognitoUserPoolEndpointResolver with expected endpointOverride', async () => { + const expectedUserPoolEndpoint = 'https://my-custom-endpoint.com'; + jest.mocked(Amplify.getConfig).mockReturnValueOnce({ + Auth: { + Cognito: { + userPoolClientId: '111111-aaaaa-42d8-891d-ee81a1549398', + userPoolId: 'us-west-2_zzzzz', + identityPoolId: 'us-west-2:xxxxxx', + userPoolEndpoint: expectedUserPoolEndpoint, + }, + }, + }); + await updateUserAttributes({ + userAttributes: {}, + options: { + clientMetadata: { foo: 'bar' }, + }, + }); + + expect(mockCreateCognitoUserPoolEndpointResolver).toHaveBeenCalledWith({ + endpointOverride: expectedUserPoolEndpoint, + }); + }); + it('updateUserAttributes API should return a map with updated attributes only', async () => { mockUpdateUserAttributes.mockResolvedValue({}); const userAttributes = { diff --git a/packages/auth/__tests__/providers/cognito/verifyTOTPSetup.test.ts b/packages/auth/__tests__/providers/cognito/verifyTOTPSetup.test.ts index aceb6ed480a..0f7c5bcb109 100644 --- a/packages/auth/__tests__/providers/cognito/verifyTOTPSetup.test.ts +++ b/packages/auth/__tests__/providers/cognito/verifyTOTPSetup.test.ts @@ -8,7 +8,8 @@ import { AuthError } from '../../../src/errors/AuthError'; import { AuthValidationErrorCode } from '../../../src/errors/types/validation'; import { VerifySoftwareTokenException } from '../../../src/providers/cognito/types/errors'; import { verifyTOTPSetup } from '../../../src/providers/cognito'; -import { verifySoftwareToken } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; +import { createVerifySoftwareTokenClient } from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../../../src/providers/cognito/factories'; import { getMockError, mockAccessToken } from './testUtils/data'; import { setUpGetConfig } from './testUtils/setUpGetConfig'; @@ -22,15 +23,22 @@ jest.mock('@aws-amplify/core/internals/utils', () => ({ isBrowser: jest.fn(() => false), })); jest.mock( - '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider', + '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider', ); +jest.mock('../../../src/providers/cognito/factories'); describe('verifyTOTPSetup', () => { const code = '123456'; const friendlyDeviceName = 'FriendlyDeviceName'; // assert mocks const mockFetchAuthSession = fetchAuthSession as jest.Mock; - const mockVerifySoftwareToken = verifySoftwareToken as jest.Mock; + const mockVerifySoftwareToken = jest.fn(); + const mockCreateVerifySoftwareTokenClient = jest.mocked( + createVerifySoftwareTokenClient, + ); + const mockCreateCognitoUserPoolEndpointResolver = jest.mocked( + createCognitoUserPoolEndpointResolver, + ); beforeAll(() => { setUpGetConfig(Amplify); @@ -41,11 +49,15 @@ describe('verifyTOTPSetup', () => { beforeEach(() => { mockVerifySoftwareToken.mockResolvedValue({}); + mockCreateVerifySoftwareTokenClient.mockReturnValueOnce( + mockVerifySoftwareToken, + ); }); afterEach(() => { mockVerifySoftwareToken.mockReset(); mockFetchAuthSession.mockClear(); + mockCreateVerifySoftwareTokenClient.mockClear(); }); it('should return successful response', async () => { @@ -64,6 +76,29 @@ describe('verifyTOTPSetup', () => { ); }); + it('invokes mockCreateCognitoUserPoolEndpointResolver with expected endpointOverride', async () => { + const expectedUserPoolEndpoint = 'https://my-custom-endpoint.com'; + jest.mocked(Amplify.getConfig).mockReturnValueOnce({ + Auth: { + Cognito: { + userPoolClientId: '111111-aaaaa-42d8-891d-ee81a1549398', + userPoolId: 'us-west-2_zzzzz', + identityPoolId: 'us-west-2:xxxxxx', + userPoolEndpoint: expectedUserPoolEndpoint, + }, + }, + }); + + await verifyTOTPSetup({ + code, + options: { friendlyDeviceName }, + }); + + expect(mockCreateCognitoUserPoolEndpointResolver).toHaveBeenCalledWith({ + endpointOverride: expectedUserPoolEndpoint, + }); + }); + it('should throw an error when code is empty', async () => { expect.assertions(2); try { diff --git a/packages/auth/src/foundation/cognitoUserPoolEndpointResolver.ts b/packages/auth/src/foundation/cognitoUserPoolEndpointResolver.ts new file mode 100644 index 00000000000..dc57e2e0ce4 --- /dev/null +++ b/packages/auth/src/foundation/cognitoUserPoolEndpointResolver.ts @@ -0,0 +1,17 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { + EndpointResolverOptions, + getDnsSuffix, +} from '@aws-amplify/core/internals/aws-client-utils'; +import { AmplifyUrl } from '@aws-amplify/core/internals/utils'; + +import { COGNITO_IDP_SERVICE_NAME } from './constants'; + +export const cognitoUserPoolEndpointResolver = ({ + region, +}: EndpointResolverOptions): { url: URL } => ({ + url: new AmplifyUrl( + `https://${COGNITO_IDP_SERVICE_NAME}.${region}.${getDnsSuffix(region)}`, + ), +}); diff --git a/packages/auth/src/foundation/constants.ts b/packages/auth/src/foundation/constants.ts new file mode 100644 index 00000000000..56814b3e66f --- /dev/null +++ b/packages/auth/src/foundation/constants.ts @@ -0,0 +1,6 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +/** + * The service name used to sign requests if the API requires authentication. + */ +export const COGNITO_IDP_SERVICE_NAME = 'cognito-idp'; diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/constants.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/constants.ts new file mode 100644 index 00000000000..8898f8bc32a --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/constants.ts @@ -0,0 +1,19 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { + getRetryDecider, + jitteredBackoff, + parseJsonError, +} from '@aws-amplify/core/internals/aws-client-utils'; +import { getAmplifyUserAgent } from '@aws-amplify/core/internals/utils'; + +import { COGNITO_IDP_SERVICE_NAME } from '../../../constants'; + +export const DEFAULT_SERVICE_CLIENT_API_CONFIG = { + service: COGNITO_IDP_SERVICE_NAME, + retryDecider: getRetryDecider(parseJsonError), + computeDelay: jitteredBackoff, + userAgentValue: getAmplifyUserAgent(), + cache: 'no-store', +}; diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createAssociateSoftwareTokenClient.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createAssociateSoftwareTokenClient.ts new file mode 100644 index 00000000000..4fa07c8a217 --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createAssociateSoftwareTokenClient.ts @@ -0,0 +1,30 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import { + AssociateSoftwareTokenCommandInput, + AssociateSoftwareTokenCommandOutput, + ServiceClientFactoryInput, +} from './types'; +import { cognitoUserPoolTransferHandler } from './shared/handler'; +import { + createUserPoolDeserializer, + createUserPoolSerializer, +} from './shared/serde'; +import { DEFAULT_SERVICE_CLIENT_API_CONFIG } from './constants'; + +export const createAssociateSoftwareTokenClient = ( + config: ServiceClientFactoryInput, +) => + composeServiceApi( + cognitoUserPoolTransferHandler, + createUserPoolSerializer( + 'AssociateSoftwareToken', + ), + createUserPoolDeserializer(), + { + ...DEFAULT_SERVICE_CLIENT_API_CONFIG, + ...config, + }, + ); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createChangePasswordClient.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createChangePasswordClient.ts new file mode 100644 index 00000000000..f8e76959850 --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createChangePasswordClient.ts @@ -0,0 +1,26 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import { cognitoUserPoolTransferHandler } from './shared/handler'; +import { + createUserPoolDeserializer, + createUserPoolSerializer, +} from './shared/serde'; +import { + ChangePasswordCommandInput, + ChangePasswordCommandOutput, + ServiceClientFactoryInput, +} from './types'; +import { DEFAULT_SERVICE_CLIENT_API_CONFIG } from './constants'; + +export const createChangePasswordClient = (config: ServiceClientFactoryInput) => + composeServiceApi( + cognitoUserPoolTransferHandler, + createUserPoolSerializer('ChangePassword'), + createUserPoolDeserializer(), + { + ...DEFAULT_SERVICE_CLIENT_API_CONFIG, + ...config, + }, + ); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createConfirmDeviceClient.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createConfirmDeviceClient.ts new file mode 100644 index 00000000000..3d9ced2e060 --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createConfirmDeviceClient.ts @@ -0,0 +1,26 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import { cognitoUserPoolTransferHandler } from './shared/handler'; +import { + createUserPoolDeserializer, + createUserPoolSerializer, +} from './shared/serde'; +import { + ConfirmDeviceCommandInput, + ConfirmDeviceCommandOutput, + ServiceClientFactoryInput, +} from './types'; +import { DEFAULT_SERVICE_CLIENT_API_CONFIG } from './constants'; + +export const createConfirmDeviceClient = (config: ServiceClientFactoryInput) => + composeServiceApi( + cognitoUserPoolTransferHandler, + createUserPoolSerializer('ConfirmDevice'), + createUserPoolDeserializer(), + { + ...DEFAULT_SERVICE_CLIENT_API_CONFIG, + ...config, + }, + ); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createConfirmForgotPasswordClient.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createConfirmForgotPasswordClient.ts new file mode 100644 index 00000000000..a300a4ccadb --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createConfirmForgotPasswordClient.ts @@ -0,0 +1,30 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import { + ConfirmForgotPasswordCommandInput, + ConfirmForgotPasswordCommandOutput, + ServiceClientFactoryInput, +} from './types'; +import { cognitoUserPoolTransferHandler } from './shared/handler'; +import { + createUserPoolDeserializer, + createUserPoolSerializer, +} from './shared/serde'; +import { DEFAULT_SERVICE_CLIENT_API_CONFIG } from './constants'; + +export const createConfirmForgotPasswordClient = ( + config: ServiceClientFactoryInput, +) => + composeServiceApi( + cognitoUserPoolTransferHandler, + createUserPoolSerializer( + 'ConfirmForgotPassword', + ), + createUserPoolDeserializer(), + { + ...DEFAULT_SERVICE_CLIENT_API_CONFIG, + ...config, + }, + ); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createConfirmSignUpClient.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createConfirmSignUpClient.ts new file mode 100644 index 00000000000..d5a712af669 --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createConfirmSignUpClient.ts @@ -0,0 +1,26 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import { DEFAULT_SERVICE_CLIENT_API_CONFIG } from './constants'; +import { cognitoUserPoolTransferHandler } from './shared/handler'; +import { + createUserPoolDeserializer, + createUserPoolSerializer, +} from './shared/serde'; +import { + ConfirmSignUpCommandInput, + ConfirmSignUpCommandOutput, + ServiceClientFactoryInput, +} from './types'; + +export const createConfirmSignUpClient = (config: ServiceClientFactoryInput) => + composeServiceApi( + cognitoUserPoolTransferHandler, + createUserPoolSerializer('ConfirmSignUp'), + createUserPoolDeserializer(), + { + ...DEFAULT_SERVICE_CLIENT_API_CONFIG, + ...config, + }, + ); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createDeleteUserAttributesClient.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createDeleteUserAttributesClient.ts new file mode 100644 index 00000000000..052ff8c9b0a --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createDeleteUserAttributesClient.ts @@ -0,0 +1,30 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import { + DeleteUserAttributesCommandInput, + DeleteUserAttributesCommandOutput, + ServiceClientFactoryInput, +} from './types'; +import { cognitoUserPoolTransferHandler } from './shared/handler'; +import { + createUserPoolDeserializer, + createUserPoolSerializer, +} from './shared/serde'; +import { DEFAULT_SERVICE_CLIENT_API_CONFIG } from './constants'; + +export const createDeleteUserAttributesClient = ( + config: ServiceClientFactoryInput, +) => + composeServiceApi( + cognitoUserPoolTransferHandler, + createUserPoolSerializer( + 'DeleteUserAttributes', + ), + createUserPoolDeserializer(), + { + ...DEFAULT_SERVICE_CLIENT_API_CONFIG, + ...config, + }, + ); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createDeleteUserClient.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createDeleteUserClient.ts new file mode 100644 index 00000000000..70cb9860ee2 --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createDeleteUserClient.ts @@ -0,0 +1,26 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import { + DeleteUserCommandInput, + DeleteUserCommandOutput, + ServiceClientFactoryInput, +} from './types'; +import { cognitoUserPoolTransferHandler } from './shared/handler'; +import { + createEmptyResponseDeserializer, + createUserPoolSerializer, +} from './shared/serde'; +import { DEFAULT_SERVICE_CLIENT_API_CONFIG } from './constants'; + +export const createDeleteUserClient = (config: ServiceClientFactoryInput) => + composeServiceApi( + cognitoUserPoolTransferHandler, + createUserPoolSerializer('DeleteUser'), + createEmptyResponseDeserializer(), + { + ...DEFAULT_SERVICE_CLIENT_API_CONFIG, + ...config, + }, + ); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createForgetDeviceClient.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createForgetDeviceClient.ts new file mode 100644 index 00000000000..f2851a80f78 --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createForgetDeviceClient.ts @@ -0,0 +1,26 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import { cognitoUserPoolTransferHandler } from './shared/handler'; +import { + createEmptyResponseDeserializer, + createUserPoolSerializer, +} from './shared/serde'; +import { + ForgetDeviceCommandInput, + ForgetDeviceCommandOutput, + ServiceClientFactoryInput, +} from './types'; +import { DEFAULT_SERVICE_CLIENT_API_CONFIG } from './constants'; + +export const createForgetDeviceClient = (config: ServiceClientFactoryInput) => + composeServiceApi( + cognitoUserPoolTransferHandler, + createUserPoolSerializer('ForgetDevice'), + createEmptyResponseDeserializer(), + { + ...DEFAULT_SERVICE_CLIENT_API_CONFIG, + ...config, + }, + ); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createForgotPasswordClient.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createForgotPasswordClient.ts new file mode 100644 index 00000000000..965e8475d83 --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createForgotPasswordClient.ts @@ -0,0 +1,26 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import { + ForgotPasswordCommandInput, + ForgotPasswordCommandOutput, + ServiceClientFactoryInput, +} from './types'; +import { cognitoUserPoolTransferHandler } from './shared/handler'; +import { + createUserPoolDeserializer, + createUserPoolSerializer, +} from './shared/serde'; +import { DEFAULT_SERVICE_CLIENT_API_CONFIG } from './constants'; + +export const createForgotPasswordClient = (config: ServiceClientFactoryInput) => + composeServiceApi( + cognitoUserPoolTransferHandler, + createUserPoolSerializer('ForgotPassword'), + createUserPoolDeserializer(), + { + ...DEFAULT_SERVICE_CLIENT_API_CONFIG, + ...config, + }, + ); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createGetUserAttributeVerificationCodeClient.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createGetUserAttributeVerificationCodeClient.ts new file mode 100644 index 00000000000..4b699383ffe --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createGetUserAttributeVerificationCodeClient.ts @@ -0,0 +1,30 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import { + GetUserAttributeVerificationCodeCommandInput, + GetUserAttributeVerificationCodeCommandOutput, + ServiceClientFactoryInput, +} from './types'; +import { cognitoUserPoolTransferHandler } from './shared/handler'; +import { + createUserPoolDeserializer, + createUserPoolSerializer, +} from './shared/serde'; +import { DEFAULT_SERVICE_CLIENT_API_CONFIG } from './constants'; + +export const createGetUserAttributeVerificationCodeClient = ( + config: ServiceClientFactoryInput, +) => + composeServiceApi( + cognitoUserPoolTransferHandler, + createUserPoolSerializer( + 'GetUserAttributeVerificationCode', + ), + createUserPoolDeserializer(), + { + ...DEFAULT_SERVICE_CLIENT_API_CONFIG, + ...config, + }, + ); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createGetUserClient.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createGetUserClient.ts new file mode 100644 index 00000000000..0a0eed9f070 --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createGetUserClient.ts @@ -0,0 +1,26 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import { + GetUserCommandInput, + GetUserCommandOutput, + ServiceClientFactoryInput, +} from './types'; +import { cognitoUserPoolTransferHandler } from './shared/handler'; +import { + createUserPoolDeserializer, + createUserPoolSerializer, +} from './shared/serde'; +import { DEFAULT_SERVICE_CLIENT_API_CONFIG } from './constants'; + +export const createGetUserClient = (config: ServiceClientFactoryInput) => + composeServiceApi( + cognitoUserPoolTransferHandler, + createUserPoolSerializer('GetUser'), + createUserPoolDeserializer(), + { + ...DEFAULT_SERVICE_CLIENT_API_CONFIG, + ...config, + }, + ); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createGlobalSignOutClient.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createGlobalSignOutClient.ts new file mode 100644 index 00000000000..3ef65818bbf --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createGlobalSignOutClient.ts @@ -0,0 +1,26 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import { + GlobalSignOutCommandInput, + GlobalSignOutCommandOutput, + ServiceClientFactoryInput, +} from './types'; +import { cognitoUserPoolTransferHandler } from './shared/handler'; +import { + createUserPoolDeserializer, + createUserPoolSerializer, +} from './shared/serde'; +import { DEFAULT_SERVICE_CLIENT_API_CONFIG } from './constants'; + +export const createGlobalSignOutClient = (config: ServiceClientFactoryInput) => + composeServiceApi( + cognitoUserPoolTransferHandler, + createUserPoolSerializer('GlobalSignOut'), + createUserPoolDeserializer(), + { + ...DEFAULT_SERVICE_CLIENT_API_CONFIG, + ...config, + }, + ); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createInitiateAuthClient.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createInitiateAuthClient.ts new file mode 100644 index 00000000000..b505144933e --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createInitiateAuthClient.ts @@ -0,0 +1,27 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import { + InitiateAuthCommandInput, + InitiateAuthCommandOutput, + ServiceClientFactoryInput, +} from './types'; +import { + createUserPoolDeserializer, + createUserPoolSerializer, +} from './shared/serde'; +import { cognitoUserPoolTransferHandler } from './shared/handler'; +import { DEFAULT_SERVICE_CLIENT_API_CONFIG } from './constants'; + +export const createInitiateAuthClient = (config: ServiceClientFactoryInput) => + composeServiceApi( + cognitoUserPoolTransferHandler, + createUserPoolSerializer('InitiateAuth'), + createUserPoolDeserializer(), + { + ...DEFAULT_SERVICE_CLIENT_API_CONFIG, + ...config, + }, + ); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createListDevicesClient.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createListDevicesClient.ts new file mode 100644 index 00000000000..b6ec1ffd385 --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createListDevicesClient.ts @@ -0,0 +1,26 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import { + ListDevicesCommandInput, + ListDevicesCommandOutput, + ServiceClientFactoryInput, +} from './types'; +import { cognitoUserPoolTransferHandler } from './shared/handler'; +import { + createUserPoolDeserializer, + createUserPoolSerializer, +} from './shared/serde'; +import { DEFAULT_SERVICE_CLIENT_API_CONFIG } from './constants'; + +export const createListDevicesClient = (config: ServiceClientFactoryInput) => + composeServiceApi( + cognitoUserPoolTransferHandler, + createUserPoolSerializer('ListDevices'), + createUserPoolDeserializer(), + { + ...DEFAULT_SERVICE_CLIENT_API_CONFIG, + ...config, + }, + ); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createResendConfirmationCodeClient.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createResendConfirmationCodeClient.ts new file mode 100644 index 00000000000..7fda8d140c5 --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createResendConfirmationCodeClient.ts @@ -0,0 +1,30 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import { + ResendConfirmationCodeCommandInput, + ResendConfirmationCodeCommandOutput, + ServiceClientFactoryInput, +} from './types'; +import { cognitoUserPoolTransferHandler } from './shared/handler'; +import { + createUserPoolDeserializer, + createUserPoolSerializer, +} from './shared/serde'; +import { DEFAULT_SERVICE_CLIENT_API_CONFIG } from './constants'; + +export const createResendConfirmationCodeClient = ( + config: ServiceClientFactoryInput, +) => + composeServiceApi( + cognitoUserPoolTransferHandler, + createUserPoolSerializer( + 'ResendConfirmationCode', + ), + createUserPoolDeserializer(), + { + ...DEFAULT_SERVICE_CLIENT_API_CONFIG, + ...config, + }, + ); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createRespondToAuthChallengeClient.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createRespondToAuthChallengeClient.ts new file mode 100644 index 00000000000..736fdfd0ed7 --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createRespondToAuthChallengeClient.ts @@ -0,0 +1,30 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import { + RespondToAuthChallengeCommandInput, + RespondToAuthChallengeCommandOutput, + ServiceClientFactoryInput, +} from './types'; +import { cognitoUserPoolTransferHandler } from './shared/handler'; +import { + createUserPoolDeserializer, + createUserPoolSerializer, +} from './shared/serde'; +import { DEFAULT_SERVICE_CLIENT_API_CONFIG } from './constants'; + +export const createRespondToAuthChallengeClient = ( + config: ServiceClientFactoryInput, +) => + composeServiceApi( + cognitoUserPoolTransferHandler, + createUserPoolSerializer( + 'RespondToAuthChallenge', + ), + createUserPoolDeserializer(), + { + ...DEFAULT_SERVICE_CLIENT_API_CONFIG, + ...config, + }, + ); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createRevokeTokenClient.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createRevokeTokenClient.ts new file mode 100644 index 00000000000..4deb8a8faf3 --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createRevokeTokenClient.ts @@ -0,0 +1,29 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import { cognitoUserPoolTransferHandler } from './shared/handler'; +import { + createUserPoolDeserializer, + createUserPoolSerializer, +} from './shared/serde'; +import { ServiceClientFactoryInput } from './types'; +import { DEFAULT_SERVICE_CLIENT_API_CONFIG } from './constants'; + +interface RevokeTokenInput { + Token: string; + ClientId: string; +} + +type RevokeTokenOutput = Record; + +export const createRevokeTokenClient = (config: ServiceClientFactoryInput) => + composeServiceApi( + cognitoUserPoolTransferHandler, + createUserPoolSerializer('RevokeToken'), + createUserPoolDeserializer(), + { + ...DEFAULT_SERVICE_CLIENT_API_CONFIG, + ...config, + }, + ); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createSetUserMFAPreferenceClient.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createSetUserMFAPreferenceClient.ts new file mode 100644 index 00000000000..60b0f4bfddd --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createSetUserMFAPreferenceClient.ts @@ -0,0 +1,30 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import { + ServiceClientFactoryInput, + SetUserMFAPreferenceCommandInput, + SetUserMFAPreferenceCommandOutput, +} from './types'; +import { cognitoUserPoolTransferHandler } from './shared/handler'; +import { + createUserPoolDeserializer, + createUserPoolSerializer, +} from './shared/serde'; +import { DEFAULT_SERVICE_CLIENT_API_CONFIG } from './constants'; + +export const createSetUserMFAPreferenceClient = ( + config: ServiceClientFactoryInput, +) => + composeServiceApi( + cognitoUserPoolTransferHandler, + createUserPoolSerializer( + 'SetUserMFAPreference', + ), + createUserPoolDeserializer(), + { + ...DEFAULT_SERVICE_CLIENT_API_CONFIG, + ...config, + }, + ); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createSignUpClient.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createSignUpClient.ts new file mode 100644 index 00000000000..e77676bab1d --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createSignUpClient.ts @@ -0,0 +1,26 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import { + ServiceClientFactoryInput, + SignUpCommandInput, + SignUpCommandOutput, +} from './types'; +import { DEFAULT_SERVICE_CLIENT_API_CONFIG } from './constants'; +import { cognitoUserPoolTransferHandler } from './shared/handler'; +import { + createUserPoolDeserializer, + createUserPoolSerializer, +} from './shared/serde'; + +export const createSignUpClient = (config: ServiceClientFactoryInput) => + composeServiceApi( + cognitoUserPoolTransferHandler, + createUserPoolSerializer('SignUp'), + createUserPoolDeserializer(), + { + ...DEFAULT_SERVICE_CLIENT_API_CONFIG, + ...config, + }, + ); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createUpdateDeviceStatusClient.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createUpdateDeviceStatusClient.ts new file mode 100644 index 00000000000..9e511187ba5 --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createUpdateDeviceStatusClient.ts @@ -0,0 +1,30 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import { + ServiceClientFactoryInput, + UpdateDeviceStatusCommandInput, + UpdateDeviceStatusCommandOutput, +} from './types'; +import { cognitoUserPoolTransferHandler } from './shared/handler'; +import { + createUserPoolDeserializer, + createUserPoolSerializer, +} from './shared/serde'; +import { DEFAULT_SERVICE_CLIENT_API_CONFIG } from './constants'; + +export const createUpdateDeviceStatusClient = ( + config: ServiceClientFactoryInput, +) => + composeServiceApi( + cognitoUserPoolTransferHandler, + createUserPoolSerializer( + 'UpdateDeviceStatus', + ), + createUserPoolDeserializer(), + { + ...DEFAULT_SERVICE_CLIENT_API_CONFIG, + ...config, + }, + ); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createUpdateUserAttributesClient.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createUpdateUserAttributesClient.ts new file mode 100644 index 00000000000..5c71001c41d --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createUpdateUserAttributesClient.ts @@ -0,0 +1,30 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import { + ServiceClientFactoryInput, + UpdateUserAttributesCommandInput, + UpdateUserAttributesCommandOutput, +} from './types'; +import { cognitoUserPoolTransferHandler } from './shared/handler'; +import { + createUserPoolDeserializer, + createUserPoolSerializer, +} from './shared/serde'; +import { DEFAULT_SERVICE_CLIENT_API_CONFIG } from './constants'; + +export const createUpdateUserAttributesClient = ( + config: ServiceClientFactoryInput, +) => + composeServiceApi( + cognitoUserPoolTransferHandler, + createUserPoolSerializer( + 'UpdateUserAttributes', + ), + createUserPoolDeserializer(), + { + ...DEFAULT_SERVICE_CLIENT_API_CONFIG, + ...config, + }, + ); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createVerifySoftwareTokenClient.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createVerifySoftwareTokenClient.ts new file mode 100644 index 00000000000..c5b63486c42 --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createVerifySoftwareTokenClient.ts @@ -0,0 +1,30 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import { + ServiceClientFactoryInput, + VerifySoftwareTokenCommandInput, + VerifySoftwareTokenCommandOutput, +} from './types'; +import { cognitoUserPoolTransferHandler } from './shared/handler'; +import { + createUserPoolDeserializer, + createUserPoolSerializer, +} from './shared/serde'; +import { DEFAULT_SERVICE_CLIENT_API_CONFIG } from './constants'; + +export const createVerifySoftwareTokenClient = ( + config: ServiceClientFactoryInput, +) => + composeServiceApi( + cognitoUserPoolTransferHandler, + createUserPoolSerializer( + 'VerifySoftwareToken', + ), + createUserPoolDeserializer(), + { + ...DEFAULT_SERVICE_CLIENT_API_CONFIG, + ...config, + }, + ); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createVerifyUserAttributeClient.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createVerifyUserAttributeClient.ts new file mode 100644 index 00000000000..ad24b27c97a --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/createVerifyUserAttributeClient.ts @@ -0,0 +1,30 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; + +import { + ServiceClientFactoryInput, + VerifyUserAttributeCommandInput, + VerifyUserAttributeCommandOutput, +} from './types'; +import { cognitoUserPoolTransferHandler } from './shared/handler'; +import { + createUserPoolDeserializer, + createUserPoolSerializer, +} from './shared/serde'; +import { DEFAULT_SERVICE_CLIENT_API_CONFIG } from './constants'; + +export const createVerifyUserAttributeClient = ( + config: ServiceClientFactoryInput, +) => + composeServiceApi( + cognitoUserPoolTransferHandler, + createUserPoolSerializer( + 'VerifyUserAttribute', + ), + createUserPoolDeserializer(), + { + ...DEFAULT_SERVICE_CLIENT_API_CONFIG, + ...config, + }, + ); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/index.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/index.ts new file mode 100644 index 00000000000..2b93cd09150 --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/index.ts @@ -0,0 +1,26 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +export { createInitiateAuthClient } from './createInitiateAuthClient'; +export { createRevokeTokenClient } from './createRevokeTokenClient'; +export { createSignUpClient } from './createSignUpClient'; +export { createConfirmSignUpClient } from './createConfirmSignUpClient'; +export { createForgotPasswordClient } from './createForgotPasswordClient'; +export { createConfirmForgotPasswordClient } from './createConfirmForgotPasswordClient'; +export { createRespondToAuthChallengeClient } from './createRespondToAuthChallengeClient'; +export { createResendConfirmationCodeClient } from './createResendConfirmationCodeClient'; +export { createVerifySoftwareTokenClient } from './createVerifySoftwareTokenClient'; +export { createAssociateSoftwareTokenClient } from './createAssociateSoftwareTokenClient'; +export { createSetUserMFAPreferenceClient } from './createSetUserMFAPreferenceClient'; +export { createGetUserClient } from './createGetUserClient'; +export { createChangePasswordClient } from './createChangePasswordClient'; +export { createConfirmDeviceClient } from './createConfirmDeviceClient'; +export { createForgetDeviceClient } from './createForgetDeviceClient'; +export { createDeleteUserClient } from './createDeleteUserClient'; +export { createGetUserAttributeVerificationCodeClient } from './createGetUserAttributeVerificationCodeClient'; +export { createGlobalSignOutClient } from './createGlobalSignOutClient'; +export { createUpdateUserAttributesClient } from './createUpdateUserAttributesClient'; +export { createVerifyUserAttributeClient } from './createVerifyUserAttributeClient'; +export { createUpdateDeviceStatusClient } from './createUpdateDeviceStatusClient'; +export { createListDevicesClient } from './createListDevicesClient'; +export { createDeleteUserAttributesClient } from './createDeleteUserAttributesClient'; diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/shared/handler/cognitoUserPoolTransferHandler.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/shared/handler/cognitoUserPoolTransferHandler.ts new file mode 100644 index 00000000000..b1b917f0a08 --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/shared/handler/cognitoUserPoolTransferHandler.ts @@ -0,0 +1,37 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { composeTransferHandler } from '@aws-amplify/core/internals/aws-client-utils/composers'; +import { + HttpRequest, + Middleware, + unauthenticatedHandler, +} from '@aws-amplify/core/internals/aws-client-utils'; +import { HttpResponse } from '@aws-amplify/core/src/clients/types'; + +/** + * A Cognito Identity-specific middleware that disables caching for all requests. + */ +const disableCacheMiddlewareFactory: Middleware< + HttpRequest, + HttpResponse, + Record +> = () => (next, _) => + async function disableCacheMiddleware(request) { + request.headers['cache-control'] = 'no-store'; + + return next(request); + }; + +/** + * A Cognito Identity-specific transfer handler that does NOT sign requests, and + * disables caching. + * + * @internal + */ +export const cognitoUserPoolTransferHandler = composeTransferHandler< + [Parameters[0]], + HttpRequest, + HttpResponse, + typeof unauthenticatedHandler +>(unauthenticatedHandler, [disableCacheMiddlewareFactory]); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/shared/handler/index.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/shared/handler/index.ts new file mode 100644 index 00000000000..c0df8483e89 --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/shared/handler/index.ts @@ -0,0 +1,4 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +export { cognitoUserPoolTransferHandler } from './cognitoUserPoolTransferHandler'; diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/shared/serde/createEmptyResponseDeserializer.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/shared/serde/createEmptyResponseDeserializer.ts new file mode 100644 index 00000000000..a27f4ef0564 --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/shared/serde/createEmptyResponseDeserializer.ts @@ -0,0 +1,21 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { + HttpResponse, + parseJsonError, +} from '@aws-amplify/core/internals/aws-client-utils'; + +import { assertServiceError } from '../../../../../../errors/utils/assertServiceError'; +import { AuthError } from '../../../../../../errors/AuthError'; + +export const createEmptyResponseDeserializer = + (): ((response: HttpResponse) => Promise) => + async (response: HttpResponse): Promise => { + if (response.statusCode >= 300) { + const error = await parseJsonError(response); + assertServiceError(error); + throw new AuthError({ name: error.name, message: error.message }); + } else { + return undefined; + } + }; diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/shared/serde/createUserPoolDeserializer.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/shared/serde/createUserPoolDeserializer.ts new file mode 100644 index 00000000000..dc9c16d7d9f --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/shared/serde/createUserPoolDeserializer.ts @@ -0,0 +1,23 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { + HttpResponse, + parseJsonBody, + parseJsonError, +} from '@aws-amplify/core/internals/aws-client-utils'; + +import { assertServiceError } from '../../../../../../errors/utils/assertServiceError'; +import { AuthError } from '../../../../../../errors/AuthError'; + +export const createUserPoolDeserializer = + (): ((response: HttpResponse) => Promise) => + async (response: HttpResponse): Promise => { + if (response.statusCode >= 300) { + const error = await parseJsonError(response); + assertServiceError(error); + throw new AuthError({ name: error.name, message: error.message }); + } + + return parseJsonBody(response); + }; diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/shared/serde/createUserPoolSerializer.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/shared/serde/createUserPoolSerializer.ts new file mode 100644 index 00000000000..81f22df9312 --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/shared/serde/createUserPoolSerializer.ts @@ -0,0 +1,58 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { + Endpoint, + Headers, + HttpRequest, +} from '@aws-amplify/core/internals/aws-client-utils'; + +type ClientOperation = + | 'SignUp' + | 'ConfirmSignUp' + | 'ForgotPassword' + | 'ConfirmForgotPassword' + | 'InitiateAuth' + | 'RespondToAuthChallenge' + | 'ResendConfirmationCode' + | 'VerifySoftwareToken' + | 'AssociateSoftwareToken' + | 'SetUserMFAPreference' + | 'GetUser' + | 'ChangePassword' + | 'ConfirmDevice' + | 'ForgetDevice' + | 'DeleteUser' + | 'GetUserAttributeVerificationCode' + | 'GlobalSignOut' + | 'UpdateUserAttributes' + | 'VerifyUserAttribute' + | 'DeleteUserAttributes' + | 'UpdateDeviceStatus' + | 'ListDevices' + | 'RevokeToken'; + +export const createUserPoolSerializer = + (operation: ClientOperation) => + (input: Input, endpoint: Endpoint): HttpRequest => { + const headers = getSharedHeaders(operation); + const body = JSON.stringify(input); + + return buildHttpRpcRequest(endpoint, headers, body); + }; + +const getSharedHeaders = (operation: string): Headers => ({ + 'content-type': 'application/x-amz-json-1.1', + 'x-amz-target': `AWSCognitoIdentityProviderService.${operation}`, +}); + +const buildHttpRpcRequest = ( + { url }: Endpoint, + headers: Headers, + body: string, +): HttpRequest => ({ + headers, + url, + body, + method: 'POST', +}); diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/shared/serde/index.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/shared/serde/index.ts new file mode 100644 index 00000000000..bb805866e28 --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/shared/serde/index.ts @@ -0,0 +1,6 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +export { createUserPoolSerializer } from './createUserPoolSerializer'; +export { createUserPoolDeserializer } from './createUserPoolDeserializer'; +export { createEmptyResponseDeserializer } from './createEmptyResponseDeserializer'; diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/types/index.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/types/index.ts new file mode 100644 index 00000000000..3374c6b6194 --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/types/index.ts @@ -0,0 +1,4 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +export * from './sdk'; +export * from './serviceClient'; diff --git a/packages/auth/src/providers/cognito/utils/clients/CognitoIdentityProvider/types.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/types/sdk.ts similarity index 100% rename from packages/auth/src/providers/cognito/utils/clients/CognitoIdentityProvider/types.ts rename to packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/types/sdk.ts diff --git a/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/types/serviceClient.ts b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/types/serviceClient.ts new file mode 100644 index 00000000000..0f358133832 --- /dev/null +++ b/packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/types/serviceClient.ts @@ -0,0 +1,8 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { EndpointResolverOptions } from '@aws-amplify/core/internals/aws-client-utils'; + +export interface ServiceClientFactoryInput { + endpointResolver(options: EndpointResolverOptions): { url: URL }; +} diff --git a/packages/auth/src/foundation/parsers/index.ts b/packages/auth/src/foundation/parsers/index.ts new file mode 100644 index 00000000000..901f99a010e --- /dev/null +++ b/packages/auth/src/foundation/parsers/index.ts @@ -0,0 +1,6 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +export { + getRegionFromUserPoolId, + getRegionFromIdentityPoolId, +} from './regionParsers'; diff --git a/packages/auth/src/providers/cognito/utils/clients/CognitoIdentityProvider/utils.ts b/packages/auth/src/foundation/parsers/regionParsers.ts similarity index 86% rename from packages/auth/src/providers/cognito/utils/clients/CognitoIdentityProvider/utils.ts rename to packages/auth/src/foundation/parsers/regionParsers.ts index 2202f2dcd37..193ddee374d 100644 --- a/packages/auth/src/providers/cognito/utils/clients/CognitoIdentityProvider/utils.ts +++ b/packages/auth/src/foundation/parsers/regionParsers.ts @@ -1,9 +1,8 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +import { AuthError } from '../../errors/AuthError'; -import { AuthError } from '../../../../../errors/AuthError'; - -export function getRegion(userPoolId?: string): string { +export function getRegionFromUserPoolId(userPoolId?: string): string { const region = userPoolId?.split('_')[0]; if ( !userPoolId || diff --git a/packages/auth/src/providers/cognito/apis/confirmResetPassword.ts b/packages/auth/src/providers/cognito/apis/confirmResetPassword.ts index 29081093e5c..5c4edc100cf 100644 --- a/packages/auth/src/providers/cognito/apis/confirmResetPassword.ts +++ b/packages/auth/src/providers/cognito/apis/confirmResetPassword.ts @@ -10,11 +10,12 @@ import { import { AuthValidationErrorCode } from '../../../errors/types/validation'; import { assertValidationError } from '../../../errors/utils/assertValidationError'; import { ConfirmResetPasswordInput } from '../types'; -import { confirmForgotPassword } from '../utils/clients/CognitoIdentityProvider'; -import { getRegion } from '../utils/clients/CognitoIdentityProvider/utils'; import { ConfirmForgotPasswordException } from '../../cognito/types/errors'; import { getAuthUserAgentValue } from '../../../utils'; import { getUserContextData } from '../utils/userContextData'; +import { createConfirmForgotPasswordClient } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../factories'; +import { getRegionFromUserPoolId } from '../../../foundation/parsers'; /** * Confirms the new password and verification code to reset the password. * @@ -30,7 +31,7 @@ export async function confirmResetPassword( ): Promise { const authConfig = Amplify.getConfig().Auth?.Cognito; assertTokenProviderConfig(authConfig); - const { userPoolClientId, userPoolId } = authConfig; + const { userPoolClientId, userPoolId, userPoolEndpoint } = authConfig; const { username, newPassword } = input; assertValidationError( !!username, @@ -53,10 +54,14 @@ export async function confirmResetPassword( userPoolId, userPoolClientId, }); - + const confirmForgotPassword = createConfirmForgotPasswordClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); await confirmForgotPassword( { - region: getRegion(authConfig.userPoolId), + region: getRegionFromUserPoolId(authConfig.userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.ConfirmResetPassword), }, { diff --git a/packages/auth/src/providers/cognito/apis/confirmSignIn.ts b/packages/auth/src/providers/cognito/apis/confirmSignIn.ts index 6aad224af30..b8e8475aa42 100644 --- a/packages/auth/src/providers/cognito/apis/confirmSignIn.ts +++ b/packages/auth/src/providers/cognito/apis/confirmSignIn.ts @@ -17,7 +17,7 @@ import { } from '../utils/signInStore'; import { AuthError } from '../../../errors/AuthError'; import { - getNewDeviceMetatada, + getNewDeviceMetadata, getSignInResult, getSignInResultFromError, handleChallengeName, @@ -27,12 +27,12 @@ import { assertValidationError } from '../../../errors/utils/assertValidationErr import { AuthValidationErrorCode } from '../../../errors/types/validation'; import { AuthErrorCodes } from '../../../common/AuthErrorStrings'; import { cacheCognitoTokens } from '../tokenProvider/cacheTokens'; +import { tokenOrchestrator } from '../tokenProvider'; +import { dispatchSignedInHubEvent } from '../utils/dispatchSignedInHubEvent'; import { ChallengeName, ChallengeParameters, -} from '../utils/clients/CognitoIdentityProvider/types'; -import { tokenOrchestrator } from '../tokenProvider'; -import { dispatchSignedInHubEvent } from '../utils/dispatchSignedInHubEvent'; +} from '../../../foundation/factories/serviceClients/cognitoIdentityProvider/types'; /** * Continues or completes the sign in process when required by the initial call to `signIn`. @@ -113,11 +113,12 @@ export async function confirmSignIn( await cacheCognitoTokens({ username, ...AuthenticationResult, - NewDeviceMetadata: await getNewDeviceMetatada( - authConfig.userPoolId, - AuthenticationResult.NewDeviceMetadata, - AuthenticationResult.AccessToken, - ), + NewDeviceMetadata: await getNewDeviceMetadata({ + userPoolId: authConfig.userPoolId, + userPoolEndpoint: authConfig.userPoolEndpoint, + newDeviceMetadata: AuthenticationResult.NewDeviceMetadata, + accessToken: AuthenticationResult.AccessToken, + }), signInDetails, }); diff --git a/packages/auth/src/providers/cognito/apis/confirmSignUp.ts b/packages/auth/src/providers/cognito/apis/confirmSignUp.ts index 62fdf93a82c..92adf180210 100644 --- a/packages/auth/src/providers/cognito/apis/confirmSignUp.ts +++ b/packages/auth/src/providers/cognito/apis/confirmSignUp.ts @@ -12,8 +12,7 @@ import { ConfirmSignUpInput, ConfirmSignUpOutput } from '../types'; import { assertValidationError } from '../../../errors/utils/assertValidationError'; import { AuthValidationErrorCode } from '../../../errors/types/validation'; import { ConfirmSignUpException } from '../types/errors'; -import { confirmSignUp as confirmSignUpClient } from '../utils/clients/CognitoIdentityProvider'; -import { getRegion } from '../utils/clients/CognitoIdentityProvider/utils'; +import { getRegionFromUserPoolId } from '../../../foundation/parsers'; import { AutoSignInEventData } from '../types/models'; import { isAutoSignInStarted, @@ -22,6 +21,8 @@ import { } from '../utils/signUpHelpers'; import { getAuthUserAgentValue } from '../../../utils'; import { getUserContextData } from '../utils/userContextData'; +import { createConfirmSignUpClient } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../factories'; /** * Confirms a new user account. @@ -41,7 +42,7 @@ export async function confirmSignUp( const authConfig = Amplify.getConfig().Auth?.Cognito; assertTokenProviderConfig(authConfig); - const { userPoolId, userPoolClientId } = authConfig; + const { userPoolId, userPoolClientId, userPoolEndpoint } = authConfig; const clientMetadata = options?.clientMetadata; assertValidationError( !!username, @@ -58,9 +59,15 @@ export async function confirmSignUp( userPoolClientId, }); + const confirmSignUpClient = createConfirmSignUpClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); + await confirmSignUpClient( { - region: getRegion(authConfig.userPoolId), + region: getRegionFromUserPoolId(authConfig.userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.ConfirmSignUp), }, { diff --git a/packages/auth/src/providers/cognito/apis/confirmUserAttribute.ts b/packages/auth/src/providers/cognito/apis/confirmUserAttribute.ts index 951a97f2822..8c0c4dba1ad 100644 --- a/packages/auth/src/providers/cognito/apis/confirmUserAttribute.ts +++ b/packages/auth/src/providers/cognito/apis/confirmUserAttribute.ts @@ -9,12 +9,13 @@ import { import { AuthValidationErrorCode } from '../../../errors/types/validation'; import { assertValidationError } from '../../../errors/utils/assertValidationError'; -import { verifyUserAttribute } from '../utils/clients/CognitoIdentityProvider'; import { VerifyUserAttributeException } from '../types/errors'; -import { getRegion } from '../utils/clients/CognitoIdentityProvider/utils'; +import { getRegionFromUserPoolId } from '../../../foundation/parsers'; import { assertAuthTokens } from '../utils/types'; import { ConfirmUserAttributeInput } from '../types'; import { getAuthUserAgentValue } from '../../../utils'; +import { createVerifyUserAttributeClient } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../factories'; /** * Confirms a user attribute with the confirmation code. @@ -30,6 +31,7 @@ export async function confirmUserAttribute( ): Promise { const authConfig = Amplify.getConfig().Auth?.Cognito; assertTokenProviderConfig(authConfig); + const { userPoolEndpoint, userPoolId } = authConfig; const { confirmationCode, userAttributeKey } = input; assertValidationError( !!confirmationCode, @@ -37,9 +39,14 @@ export async function confirmUserAttribute( ); const { tokens } = await fetchAuthSession({ forceRefresh: false }); assertAuthTokens(tokens); + const verifyUserAttribute = createVerifyUserAttributeClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); await verifyUserAttribute( { - region: getRegion(authConfig.userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.ConfirmUserAttribute), }, { diff --git a/packages/auth/src/providers/cognito/apis/deleteUser.ts b/packages/auth/src/providers/cognito/apis/deleteUser.ts index e14bde07f09..53c0c18c6dd 100644 --- a/packages/auth/src/providers/cognito/apis/deleteUser.ts +++ b/packages/auth/src/providers/cognito/apis/deleteUser.ts @@ -7,12 +7,13 @@ import { assertTokenProviderConfig, } from '@aws-amplify/core/internals/utils'; -import { getRegion } from '../utils/clients/CognitoIdentityProvider/utils'; +import { getRegionFromUserPoolId } from '../../../foundation/parsers'; import { assertAuthTokens } from '../utils/types'; -import { deleteUser as serviceDeleteUser } from '../utils/clients/CognitoIdentityProvider'; import { DeleteUserException } from '../types/errors'; import { tokenOrchestrator } from '../tokenProvider'; import { getAuthUserAgentValue } from '../../../utils'; +import { createDeleteUserClient } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../factories'; import { signOut } from './signOut'; @@ -25,13 +26,17 @@ import { signOut } from './signOut'; export async function deleteUser(): Promise { const authConfig = Amplify.getConfig().Auth?.Cognito; assertTokenProviderConfig(authConfig); - + const { userPoolEndpoint, userPoolId } = authConfig; const { tokens } = await fetchAuthSession(); assertAuthTokens(tokens); - + const serviceDeleteUser = createDeleteUserClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); await serviceDeleteUser( { - region: getRegion(authConfig.userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.DeleteUser), }, { diff --git a/packages/auth/src/providers/cognito/apis/deleteUserAttributes.ts b/packages/auth/src/providers/cognito/apis/deleteUserAttributes.ts index 5812b656d60..b958dfacc1f 100644 --- a/packages/auth/src/providers/cognito/apis/deleteUserAttributes.ts +++ b/packages/auth/src/providers/cognito/apis/deleteUserAttributes.ts @@ -7,12 +7,13 @@ import { assertTokenProviderConfig, } from '@aws-amplify/core/internals/utils'; -import { deleteUserAttributes as deleteUserAttributesClient } from '../utils/clients/CognitoIdentityProvider'; -import { getRegion } from '../utils/clients/CognitoIdentityProvider/utils'; +import { getRegionFromUserPoolId } from '../../../foundation/parsers'; import { assertAuthTokens } from '../utils/types'; import { DeleteUserAttributesInput } from '../types'; import { DeleteUserAttributesException } from '../types/errors'; import { getAuthUserAgentValue } from '../../../utils'; +import { createDeleteUserAttributesClient } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../factories'; /** * Deletes user attributes. @@ -27,11 +28,17 @@ export async function deleteUserAttributes( const authConfig = Amplify.getConfig().Auth?.Cognito; assertTokenProviderConfig(authConfig); const { userAttributeKeys } = input; + const { userPoolEndpoint, userPoolId } = authConfig; const { tokens } = await fetchAuthSession({ forceRefresh: false }); assertAuthTokens(tokens); + const deleteUserAttributesClient = createDeleteUserAttributesClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); await deleteUserAttributesClient( { - region: getRegion(authConfig.userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.DeleteUserAttributes), }, { diff --git a/packages/auth/src/providers/cognito/apis/fetchDevices.ts b/packages/auth/src/providers/cognito/apis/fetchDevices.ts index 29be20e7a78..c0dc69f22f4 100644 --- a/packages/auth/src/providers/cognito/apis/fetchDevices.ts +++ b/packages/auth/src/providers/cognito/apis/fetchDevices.ts @@ -8,12 +8,13 @@ import { } from '@aws-amplify/core/internals/utils'; import { FetchDevicesOutput } from '../types'; -import { listDevices } from '../utils/clients/CognitoIdentityProvider'; -import { DeviceType } from '../utils/clients/CognitoIdentityProvider/types'; +import { DeviceType } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider/types'; import { assertAuthTokens } from '../utils/types'; -import { getRegion } from '../utils/clients/CognitoIdentityProvider/utils'; +import { getRegionFromUserPoolId } from '../../../foundation/parsers'; import { rememberDevice } from '..'; import { getAuthUserAgentValue } from '../../../utils'; +import { createListDevicesClient } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../factories'; // Cognito Documentation for max device // https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListDevices.html#API_ListDevices_RequestSyntax @@ -30,13 +31,17 @@ const MAX_DEVICES = 60; export async function fetchDevices(): Promise { const authConfig = Amplify.getConfig().Auth?.Cognito; assertTokenProviderConfig(authConfig); - + const { userPoolEndpoint, userPoolId } = authConfig; const { tokens } = await fetchAuthSession(); assertAuthTokens(tokens); - + const listDevices = createListDevicesClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); const response = await listDevices( { - region: getRegion(authConfig.userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.FetchDevices), }, { diff --git a/packages/auth/src/providers/cognito/apis/fetchMFAPreference.ts b/packages/auth/src/providers/cognito/apis/fetchMFAPreference.ts index ef42d34f72f..e6da216ba81 100644 --- a/packages/auth/src/providers/cognito/apis/fetchMFAPreference.ts +++ b/packages/auth/src/providers/cognito/apis/fetchMFAPreference.ts @@ -10,10 +10,11 @@ import { import { FetchMFAPreferenceOutput } from '../types'; import { getMFAType, getMFATypes } from '../utils/signInHelpers'; import { GetUserException } from '../types/errors'; -import { getUser } from '../utils/clients/CognitoIdentityProvider'; -import { getRegion } from '../utils/clients/CognitoIdentityProvider/utils'; +import { getRegionFromUserPoolId } from '../../../foundation/parsers'; import { assertAuthTokens } from '../utils/types'; import { getAuthUserAgentValue } from '../../../utils'; +import { createGetUserClient } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../factories'; /** * Fetches the preferred MFA setting and enabled MFA settings for the user. @@ -26,11 +27,17 @@ import { getAuthUserAgentValue } from '../../../utils'; export async function fetchMFAPreference(): Promise { const authConfig = Amplify.getConfig().Auth?.Cognito; assertTokenProviderConfig(authConfig); + const { userPoolEndpoint, userPoolId } = authConfig; const { tokens } = await fetchAuthSession({ forceRefresh: false }); assertAuthTokens(tokens); + const getUser = createGetUserClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); const { PreferredMfaSetting, UserMFASettingList } = await getUser( { - region: getRegion(authConfig.userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.FetchMFAPreference), }, { diff --git a/packages/auth/src/providers/cognito/apis/forgetDevice.ts b/packages/auth/src/providers/cognito/apis/forgetDevice.ts index 66dd3488f7b..b1ca574e1e4 100644 --- a/packages/auth/src/providers/cognito/apis/forgetDevice.ts +++ b/packages/auth/src/providers/cognito/apis/forgetDevice.ts @@ -7,13 +7,14 @@ import { assertTokenProviderConfig, } from '@aws-amplify/core/internals/utils'; -import { forgetDevice as serviceForgetDevice } from '../utils/clients/CognitoIdentityProvider'; import { assertAuthTokens, assertDeviceMetadata } from '../utils/types'; -import { getRegion } from '../utils/clients/CognitoIdentityProvider/utils'; +import { getRegionFromUserPoolId } from '../../../foundation/parsers'; import { tokenOrchestrator } from '../tokenProvider'; import { ForgetDeviceInput } from '../types'; import { ForgetDeviceException } from '../../cognito/types/errors'; import { getAuthUserAgentValue } from '../../../utils'; +import { createForgetDeviceClient } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../factories'; /** * Forget a remembered device while authenticated. @@ -27,17 +28,21 @@ export async function forgetDevice(input?: ForgetDeviceInput): Promise { const { device: { id: externalDeviceKey } = { id: undefined } } = input ?? {}; const authConfig = Amplify.getConfig().Auth?.Cognito; assertTokenProviderConfig(authConfig); - + const { userPoolEndpoint, userPoolId } = authConfig; const { tokens } = await fetchAuthSession(); assertAuthTokens(tokens); const deviceMetadata = await tokenOrchestrator.getDeviceMetadata(); const currentDeviceKey = deviceMetadata?.deviceKey; if (!externalDeviceKey) assertDeviceMetadata(deviceMetadata); - + const serviceForgetDevice = createForgetDeviceClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); await serviceForgetDevice( { - region: getRegion(authConfig.userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.ForgetDevice), }, { diff --git a/packages/auth/src/providers/cognito/apis/internal/fetchUserAttributes.ts b/packages/auth/src/providers/cognito/apis/internal/fetchUserAttributes.ts index c1e4e9dd008..01230bf5153 100644 --- a/packages/auth/src/providers/cognito/apis/internal/fetchUserAttributes.ts +++ b/packages/auth/src/providers/cognito/apis/internal/fetchUserAttributes.ts @@ -8,26 +8,32 @@ import { fetchAuthSession, } from '@aws-amplify/core/internals/utils'; -import { getUser } from '../../utils/clients/CognitoIdentityProvider'; -import { getRegion } from '../../utils/clients/CognitoIdentityProvider/utils'; +import { getRegionFromUserPoolId } from '../../../../foundation/parsers'; import { assertAuthTokens } from '../../utils/types'; import { FetchUserAttributesOutput } from '../../types'; import { toAuthUserAttribute } from '../../utils/apiHelpers'; import { getAuthUserAgentValue } from '../../../../utils'; +import { createGetUserClient } from '../../../../foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../../factories'; export const fetchUserAttributes = async ( amplify: AmplifyClassV6, ): Promise => { const authConfig = amplify.getConfig().Auth?.Cognito; assertTokenProviderConfig(authConfig); + const { userPoolEndpoint, userPoolId } = authConfig; const { tokens } = await fetchAuthSession(amplify, { forceRefresh: false, }); assertAuthTokens(tokens); - + const getUser = createGetUserClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); const { UserAttributes } = await getUser( { - region: getRegion(authConfig.userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.FetchUserAttributes), }, { diff --git a/packages/auth/src/providers/cognito/apis/rememberDevice.ts b/packages/auth/src/providers/cognito/apis/rememberDevice.ts index 218b7b533e6..eb24022096e 100644 --- a/packages/auth/src/providers/cognito/apis/rememberDevice.ts +++ b/packages/auth/src/providers/cognito/apis/rememberDevice.ts @@ -7,12 +7,13 @@ import { assertTokenProviderConfig, } from '@aws-amplify/core/internals/utils'; -import { updateDeviceStatus } from '../utils/clients/CognitoIdentityProvider'; import { assertAuthTokens, assertDeviceMetadata } from '../utils/types'; -import { getRegion } from '../utils/clients/CognitoIdentityProvider/utils'; +import { getRegionFromUserPoolId } from '../../../foundation/parsers'; import { tokenOrchestrator } from '../tokenProvider'; import { UpdateDeviceStatusException } from '../../cognito/types/errors'; import { getAuthUserAgentValue } from '../../../utils'; +import { createUpdateDeviceStatusClient } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../factories'; /** * Marks device as remembered while authenticated. @@ -24,16 +25,20 @@ import { getAuthUserAgentValue } from '../../../utils'; export async function rememberDevice(): Promise { const authConfig = Amplify.getConfig().Auth?.Cognito; assertTokenProviderConfig(authConfig); - + const { userPoolEndpoint, userPoolId } = authConfig; const { tokens } = await fetchAuthSession(); assertAuthTokens(tokens); const deviceMetadata = await tokenOrchestrator?.getDeviceMetadata(); assertDeviceMetadata(deviceMetadata); - + const updateDeviceStatus = createUpdateDeviceStatusClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); await updateDeviceStatus( { - region: getRegion(authConfig.userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.RememberDevice), }, { diff --git a/packages/auth/src/providers/cognito/apis/resendSignUpCode.ts b/packages/auth/src/providers/cognito/apis/resendSignUpCode.ts index 99ef3996f52..cdda7b980eb 100644 --- a/packages/auth/src/providers/cognito/apis/resendSignUpCode.ts +++ b/packages/auth/src/providers/cognito/apis/resendSignUpCode.ts @@ -12,11 +12,12 @@ import { AuthDeliveryMedium } from '../../../types'; import { assertValidationError } from '../../../errors/utils/assertValidationError'; import { AuthValidationErrorCode } from '../../../errors/types/validation'; import { ResendSignUpCodeInput, ResendSignUpCodeOutput } from '../types'; -import { getRegion } from '../utils/clients/CognitoIdentityProvider/utils'; -import { resendConfirmationCode } from '../utils/clients/CognitoIdentityProvider'; +import { getRegionFromUserPoolId } from '../../../foundation/parsers'; import { getAuthUserAgentValue } from '../../../utils'; import { getUserContextData } from '../utils/userContextData'; import { ResendConfirmationException } from '../types/errors'; +import { createResendConfirmationCodeClient } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../factories'; /** * Resend the confirmation code while signing up @@ -37,7 +38,7 @@ export async function resendSignUpCode( ); const authConfig = Amplify.getConfig().Auth?.Cognito; assertTokenProviderConfig(authConfig); - const { userPoolClientId, userPoolId } = authConfig; + const { userPoolClientId, userPoolId, userPoolEndpoint } = authConfig; const clientMetadata = input.options?.clientMetadata; const UserContextData = getUserContextData({ @@ -45,10 +46,14 @@ export async function resendSignUpCode( userPoolId, userPoolClientId, }); - + const resendConfirmationCode = createResendConfirmationCodeClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); const { CodeDeliveryDetails } = await resendConfirmationCode( { - region: getRegion(authConfig.userPoolId), + region: getRegionFromUserPoolId(authConfig.userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.ResendSignUpCode), }, { diff --git a/packages/auth/src/providers/cognito/apis/resetPassword.ts b/packages/auth/src/providers/cognito/apis/resetPassword.ts index 273a77d413d..cd6d37a39ca 100644 --- a/packages/auth/src/providers/cognito/apis/resetPassword.ts +++ b/packages/auth/src/providers/cognito/apis/resetPassword.ts @@ -12,11 +12,12 @@ import { AuthValidationErrorCode } from '../../../errors/types/validation'; import { assertValidationError } from '../../../errors/utils/assertValidationError'; import { AuthDeliveryMedium } from '../../../types'; import { ResetPasswordInput, ResetPasswordOutput } from '../types'; -import { forgotPassword } from '../utils/clients/CognitoIdentityProvider'; -import { getRegion } from '../utils/clients/CognitoIdentityProvider/utils'; +import { getRegionFromUserPoolId } from '../../../foundation/parsers'; import { ForgotPasswordException } from '../../cognito/types/errors'; import { getAuthUserAgentValue } from '../../../utils'; import { getUserContextData } from '../utils/userContextData'; +import { createForgotPasswordClient } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../factories'; /** * Resets a user's password. @@ -39,7 +40,7 @@ export async function resetPassword( ); const authConfig = Amplify.getConfig().Auth?.Cognito; assertTokenProviderConfig(authConfig); - const { userPoolClientId, userPoolId } = authConfig; + const { userPoolClientId, userPoolId, userPoolEndpoint } = authConfig; const clientMetadata = input.options?.clientMetadata; const UserContextData = getUserContextData({ @@ -48,15 +49,20 @@ export async function resetPassword( userPoolClientId, }); + const forgotPassword = createForgotPasswordClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); const res = await forgotPassword( { - region: getRegion(authConfig.userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.ResetPassword), }, { Username: username, ClientMetadata: clientMetadata, - ClientId: authConfig.userPoolClientId, + ClientId: userPoolClientId, UserContextData, }, ); diff --git a/packages/auth/src/providers/cognito/apis/sendUserAttributeVerificationCode.ts b/packages/auth/src/providers/cognito/apis/sendUserAttributeVerificationCode.ts index 55e5a8b5a84..4b04b2a85d1 100644 --- a/packages/auth/src/providers/cognito/apis/sendUserAttributeVerificationCode.ts +++ b/packages/auth/src/providers/cognito/apis/sendUserAttributeVerificationCode.ts @@ -13,11 +13,12 @@ import { SendUserAttributeVerificationCodeInput, SendUserAttributeVerificationCodeOutput, } from '../types'; -import { getUserAttributeVerificationCode } from '../utils/clients/CognitoIdentityProvider'; import { assertAuthTokens } from '../utils/types'; -import { getRegion } from '../utils/clients/CognitoIdentityProvider/utils'; +import { getRegionFromUserPoolId } from '../../../foundation/parsers'; import { GetUserAttributeVerificationException } from '../types/errors'; import { getAuthUserAgentValue } from '../../../utils'; +import { createGetUserAttributeVerificationCodeClient } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../factories'; /** * Resends user's confirmation code when updating attributes while authenticated. @@ -34,11 +35,18 @@ export const sendUserAttributeVerificationCode = async ( const authConfig = Amplify.getConfig().Auth?.Cognito; const clientMetadata = options?.clientMetadata; assertTokenProviderConfig(authConfig); + const { userPoolEndpoint, userPoolId } = authConfig; const { tokens } = await fetchAuthSession({ forceRefresh: false }); assertAuthTokens(tokens); + const getUserAttributeVerificationCode = + createGetUserAttributeVerificationCodeClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); const { CodeDeliveryDetails } = await getUserAttributeVerificationCode( { - region: getRegion(authConfig.userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue( AuthAction.SendUserAttributeVerificationCode, ), diff --git a/packages/auth/src/providers/cognito/apis/setUpTOTP.ts b/packages/auth/src/providers/cognito/apis/setUpTOTP.ts index e99b8618995..43dac4c787b 100644 --- a/packages/auth/src/providers/cognito/apis/setUpTOTP.ts +++ b/packages/auth/src/providers/cognito/apis/setUpTOTP.ts @@ -14,10 +14,11 @@ import { } from '../types/errors'; import { SetUpTOTPOutput } from '../types'; import { getTOTPSetupDetails } from '../utils/signInHelpers'; -import { associateSoftwareToken } from '../utils/clients/CognitoIdentityProvider'; -import { getRegion } from '../utils/clients/CognitoIdentityProvider/utils'; +import { getRegionFromUserPoolId } from '../../../foundation/parsers'; import { assertAuthTokens } from '../utils/types'; import { getAuthUserAgentValue } from '../../../utils'; +import { createAssociateSoftwareTokenClient } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../factories'; /** * Sets up TOTP for the user. @@ -30,12 +31,18 @@ import { getAuthUserAgentValue } from '../../../utils'; export async function setUpTOTP(): Promise { const authConfig = Amplify.getConfig().Auth?.Cognito; assertTokenProviderConfig(authConfig); + const { userPoolEndpoint, userPoolId } = authConfig; const { tokens } = await fetchAuthSession({ forceRefresh: false }); assertAuthTokens(tokens); const username = tokens.idToken?.payload['cognito:username'] ?? ''; + const associateSoftwareToken = createAssociateSoftwareTokenClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); const { SecretCode } = await associateSoftwareToken( { - region: getRegion(authConfig.userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.SetUpTOTP), }, { diff --git a/packages/auth/src/providers/cognito/apis/signInWithCustomAuth.ts b/packages/auth/src/providers/cognito/apis/signInWithCustomAuth.ts index e55e3f0a50d..a666fba0acb 100644 --- a/packages/auth/src/providers/cognito/apis/signInWithCustomAuth.ts +++ b/packages/auth/src/providers/cognito/apis/signInWithCustomAuth.ts @@ -9,7 +9,7 @@ import { assertValidationError } from '../../../errors/utils/assertValidationErr import { assertServiceError } from '../../../errors/utils/assertServiceError'; import { getActiveSignInUsername, - getNewDeviceMetatada, + getNewDeviceMetadata, getSignInResult, getSignInResultFromError, handleCustomAuthFlowWithoutSRP, @@ -29,7 +29,7 @@ import { cacheCognitoTokens } from '../tokenProvider/cacheTokens'; import { ChallengeName, ChallengeParameters, -} from '../utils/clients/CognitoIdentityProvider/types'; +} from '../../../foundation/factories/serviceClients/cognitoIdentityProvider/types'; import { tokenOrchestrator } from '../tokenProvider'; import { dispatchSignedInHubEvent } from '../utils/dispatchSignedInHubEvent'; @@ -89,11 +89,12 @@ export async function signInWithCustomAuth( await cacheCognitoTokens({ username: activeUsername, ...AuthenticationResult, - NewDeviceMetadata: await getNewDeviceMetatada( - authConfig.userPoolId, - AuthenticationResult.NewDeviceMetadata, - AuthenticationResult.AccessToken, - ), + NewDeviceMetadata: await getNewDeviceMetadata({ + userPoolId: authConfig.userPoolId, + userPoolEndpoint: authConfig.userPoolEndpoint, + newDeviceMetadata: AuthenticationResult.NewDeviceMetadata, + accessToken: AuthenticationResult.AccessToken, + }), signInDetails, }); diff --git a/packages/auth/src/providers/cognito/apis/signInWithCustomSRPAuth.ts b/packages/auth/src/providers/cognito/apis/signInWithCustomSRPAuth.ts index a67fa9f861c..a22f98b3804 100644 --- a/packages/auth/src/providers/cognito/apis/signInWithCustomSRPAuth.ts +++ b/packages/auth/src/providers/cognito/apis/signInWithCustomSRPAuth.ts @@ -9,7 +9,7 @@ import { assertValidationError } from '../../../errors/utils/assertValidationErr import { assertServiceError } from '../../../errors/utils/assertServiceError'; import { getActiveSignInUsername, - getNewDeviceMetatada, + getNewDeviceMetadata, getSignInResult, getSignInResultFromError, handleCustomSRPAuthFlow, @@ -31,7 +31,7 @@ import { cacheCognitoTokens } from '../tokenProvider/cacheTokens'; import { ChallengeName, ChallengeParameters, -} from '../utils/clients/CognitoIdentityProvider/types'; +} from '../../../foundation/factories/serviceClients/cognitoIdentityProvider/types'; import { tokenOrchestrator } from '../tokenProvider'; import { dispatchSignedInHubEvent } from '../utils/dispatchSignedInHubEvent'; @@ -92,11 +92,12 @@ export async function signInWithCustomSRPAuth( await cacheCognitoTokens({ username: activeUsername, ...AuthenticationResult, - NewDeviceMetadata: await getNewDeviceMetatada( - authConfig.userPoolId, - AuthenticationResult.NewDeviceMetadata, - AuthenticationResult.AccessToken, - ), + NewDeviceMetadata: await getNewDeviceMetadata({ + userPoolId: authConfig.userPoolId, + userPoolEndpoint: authConfig.userPoolEndpoint, + newDeviceMetadata: AuthenticationResult.NewDeviceMetadata, + accessToken: AuthenticationResult.AccessToken, + }), signInDetails, }); cleanActiveSignInState(); diff --git a/packages/auth/src/providers/cognito/apis/signInWithSRP.ts b/packages/auth/src/providers/cognito/apis/signInWithSRP.ts index 32f0ca11b99..9bb8d4deca7 100644 --- a/packages/auth/src/providers/cognito/apis/signInWithSRP.ts +++ b/packages/auth/src/providers/cognito/apis/signInWithSRP.ts @@ -10,14 +10,14 @@ import { assertServiceError } from '../../../errors/utils/assertServiceError'; import { ChallengeName, ChallengeParameters, -} from '../utils/clients/CognitoIdentityProvider/types'; +} from '../../../foundation/factories/serviceClients/cognitoIdentityProvider/types'; import { InitiateAuthException, RespondToAuthChallengeException, } from '../types/errors'; import { getActiveSignInUsername, - getNewDeviceMetatada, + getNewDeviceMetadata, getSignInResult, getSignInResultFromError, handleUserSRPAuthFlow, @@ -93,11 +93,12 @@ export async function signInWithSRP( await cacheCognitoTokens({ username: activeUsername, ...AuthenticationResult, - NewDeviceMetadata: await getNewDeviceMetatada( - authConfig.userPoolId, - AuthenticationResult.NewDeviceMetadata, - AuthenticationResult.AccessToken, - ), + NewDeviceMetadata: await getNewDeviceMetadata({ + userPoolId: authConfig.userPoolId, + userPoolEndpoint: authConfig.userPoolEndpoint, + newDeviceMetadata: AuthenticationResult.NewDeviceMetadata, + accessToken: AuthenticationResult.AccessToken, + }), signInDetails, }); diff --git a/packages/auth/src/providers/cognito/apis/signInWithUserPassword.ts b/packages/auth/src/providers/cognito/apis/signInWithUserPassword.ts index e1de730cb1c..071f54f8313 100644 --- a/packages/auth/src/providers/cognito/apis/signInWithUserPassword.ts +++ b/packages/auth/src/providers/cognito/apis/signInWithUserPassword.ts @@ -10,10 +10,10 @@ import { assertValidationError } from '../../../errors/utils/assertValidationErr import { ChallengeName, ChallengeParameters, -} from '../utils/clients/CognitoIdentityProvider/types'; +} from '../../../foundation/factories/serviceClients/cognitoIdentityProvider/types'; import { getActiveSignInUsername, - getNewDeviceMetatada, + getNewDeviceMetadata, getSignInResult, getSignInResultFromError, handleUserPasswordAuthFlow, @@ -87,11 +87,12 @@ export async function signInWithUserPassword( await cacheCognitoTokens({ ...AuthenticationResult, username: activeUsername, - NewDeviceMetadata: await getNewDeviceMetatada( - authConfig.userPoolId, - AuthenticationResult.NewDeviceMetadata, - AuthenticationResult.AccessToken, - ), + NewDeviceMetadata: await getNewDeviceMetadata({ + userPoolId: authConfig.userPoolId, + userPoolEndpoint: authConfig.userPoolEndpoint, + newDeviceMetadata: AuthenticationResult.NewDeviceMetadata, + accessToken: AuthenticationResult.AccessToken, + }), signInDetails, }); cleanActiveSignInState(); diff --git a/packages/auth/src/providers/cognito/apis/signOut.ts b/packages/auth/src/providers/cognito/apis/signOut.ts index e073129ca10..2fa52b73ee4 100644 --- a/packages/auth/src/providers/cognito/apis/signOut.ts +++ b/packages/auth/src/providers/cognito/apis/signOut.ts @@ -20,11 +20,7 @@ import { import { getAuthUserAgentValue } from '../../../utils'; import { SignOutInput } from '../types'; import { tokenOrchestrator } from '../tokenProvider'; -import { - globalSignOut as globalSignOutClient, - revokeToken, -} from '../utils/clients/CognitoIdentityProvider'; -import { getRegion } from '../utils/clients/CognitoIdentityProvider/utils'; +import { getRegionFromUserPoolId } from '../../../foundation/parsers'; import { assertAuthTokens, assertAuthTokensWithRefreshToken, @@ -33,6 +29,11 @@ import { handleOAuthSignOut } from '../utils/oauth'; import { DefaultOAuthStore } from '../utils/signInWithRedirectStore'; import { AuthError } from '../../../errors/AuthError'; import { OAUTH_SIGNOUT_EXCEPTION } from '../../../errors/constants'; +import { + createGlobalSignOutClient, + createRevokeTokenClient, +} from '../../../foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../factories'; const logger = new ConsoleLogger('Auth'); @@ -86,16 +87,23 @@ export async function signOut(input?: SignOutInput): Promise { async function clientSignOut(cognitoConfig: CognitoUserPoolConfig) { try { + const { userPoolEndpoint, userPoolId, userPoolClientId } = cognitoConfig; const authTokens = await tokenOrchestrator.getTokenStore().loadTokens(); assertAuthTokensWithRefreshToken(authTokens); if (isSessionRevocable(authTokens.accessToken)) { + const revokeToken = createRevokeTokenClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); + await revokeToken( { - region: getRegion(cognitoConfig.userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.SignOut), }, { - ClientId: cognitoConfig.userPoolClientId, + ClientId: userPoolClientId, Token: authTokens.refreshToken, }, ); @@ -110,11 +118,17 @@ async function clientSignOut(cognitoConfig: CognitoUserPoolConfig) { async function globalSignOut(cognitoConfig: CognitoUserPoolConfig) { try { + const { userPoolEndpoint, userPoolId } = cognitoConfig; const authTokens = await tokenOrchestrator.getTokenStore().loadTokens(); assertAuthTokens(authTokens); + const globalSignOutClient = createGlobalSignOutClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); await globalSignOutClient( { - region: getRegion(cognitoConfig.userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.SignOut), }, { diff --git a/packages/auth/src/providers/cognito/apis/signUp.ts b/packages/auth/src/providers/cognito/apis/signUp.ts index ef9aef32fa2..3ec246648f5 100644 --- a/packages/auth/src/providers/cognito/apis/signUp.ts +++ b/packages/auth/src/providers/cognito/apis/signUp.ts @@ -10,11 +10,10 @@ import { import { AuthDeliveryMedium } from '../../../types'; import { SignInInput, SignUpInput, SignUpOutput } from '../types'; -import { signUp as signUpClient } from '../utils/clients/CognitoIdentityProvider'; import { assertValidationError } from '../../../errors/utils/assertValidationError'; import { AuthValidationErrorCode } from '../../../errors/types/validation'; import { SignUpException } from '../types/errors'; -import { getRegion } from '../utils/clients/CognitoIdentityProvider/utils'; +import { getRegionFromUserPoolId } from '../../../foundation/parsers'; import { toAttributeType } from '../utils/apiHelpers'; import { autoSignInUserConfirmed, @@ -27,6 +26,8 @@ import { } from '../utils/signUpHelpers'; import { getUserContextData } from '../utils/userContextData'; import { getAuthUserAgentValue } from '../../../utils'; +import { createSignUpClient } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../factories'; import { setAutoSignIn } from './autoSignIn'; @@ -72,11 +73,15 @@ export async function signUp(input: SignUpInput): Promise { setAutoSignInStarted(true); } - const { userPoolId, userPoolClientId } = authConfig; - + const { userPoolId, userPoolClientId, userPoolEndpoint } = authConfig; + const signUpClient = createSignUpClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); const clientOutput = await signUpClient( { - region: getRegion(userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.SignUp), }, { diff --git a/packages/auth/src/providers/cognito/apis/updateMFAPreference.ts b/packages/auth/src/providers/cognito/apis/updateMFAPreference.ts index 790cc82f8bd..5f87522af5a 100644 --- a/packages/auth/src/providers/cognito/apis/updateMFAPreference.ts +++ b/packages/auth/src/providers/cognito/apis/updateMFAPreference.ts @@ -10,11 +10,12 @@ import { import { UpdateMFAPreferenceInput } from '../types'; import { SetUserMFAPreferenceException } from '../types/errors'; import { MFAPreference } from '../types/models'; -import { setUserMFAPreference } from '../utils/clients/CognitoIdentityProvider'; -import { getRegion } from '../utils/clients/CognitoIdentityProvider/utils'; -import { CognitoMFASettings } from '../utils/clients/CognitoIdentityProvider/types'; +import { getRegionFromUserPoolId } from '../../../foundation/parsers'; +import { CognitoMFASettings } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider/types'; import { assertAuthTokens } from '../utils/types'; import { getAuthUserAgentValue } from '../../../utils'; +import { createSetUserMFAPreferenceClient } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../factories'; /** * Updates the MFA preference of the user. @@ -29,11 +30,17 @@ export async function updateMFAPreference( const { sms, totp } = input; const authConfig = Amplify.getConfig().Auth?.Cognito; assertTokenProviderConfig(authConfig); + const { userPoolEndpoint, userPoolId } = authConfig; const { tokens } = await fetchAuthSession({ forceRefresh: false }); assertAuthTokens(tokens); + const setUserMFAPreference = createSetUserMFAPreferenceClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); await setUserMFAPreference( { - region: getRegion(authConfig.userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.UpdateMFAPreference), }, { diff --git a/packages/auth/src/providers/cognito/apis/updatePassword.ts b/packages/auth/src/providers/cognito/apis/updatePassword.ts index 0f83fc9f1df..f8c8c4bdeae 100644 --- a/packages/auth/src/providers/cognito/apis/updatePassword.ts +++ b/packages/auth/src/providers/cognito/apis/updatePassword.ts @@ -10,11 +10,12 @@ import { import { AuthValidationErrorCode } from '../../../errors/types/validation'; import { assertValidationError } from '../../../errors/utils/assertValidationError'; import { UpdatePasswordInput } from '../types'; -import { changePassword } from '../utils/clients/CognitoIdentityProvider'; import { ChangePasswordException } from '../../cognito/types/errors'; -import { getRegion } from '../utils/clients/CognitoIdentityProvider/utils'; +import { getRegionFromUserPoolId } from '../../../foundation/parsers'; import { assertAuthTokens } from '../utils/types'; import { getAuthUserAgentValue } from '../../../utils'; +import { createChangePasswordClient } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../factories'; /** * Updates user's password while authenticated. @@ -29,6 +30,7 @@ export async function updatePassword( ): Promise { const authConfig = Amplify.getConfig().Auth?.Cognito; assertTokenProviderConfig(authConfig); + const { userPoolEndpoint, userPoolId } = authConfig; const { oldPassword, newPassword } = input; assertValidationError( !!oldPassword, @@ -41,9 +43,14 @@ export async function updatePassword( ); const { tokens } = await fetchAuthSession({ forceRefresh: false }); assertAuthTokens(tokens); + const changePassword = createChangePasswordClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); await changePassword( { - region: getRegion(authConfig.userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.UpdatePassword), }, { diff --git a/packages/auth/src/providers/cognito/apis/updateUserAttributes.ts b/packages/auth/src/providers/cognito/apis/updateUserAttributes.ts index b0e6cc7f3f7..5076e3145a5 100644 --- a/packages/auth/src/providers/cognito/apis/updateUserAttributes.ts +++ b/packages/auth/src/providers/cognito/apis/updateUserAttributes.ts @@ -16,13 +16,14 @@ import { UpdateUserAttributesInput, UpdateUserAttributesOutput, } from '../types'; -import { updateUserAttributes as updateUserAttributesClient } from '../utils/clients/CognitoIdentityProvider'; import { assertAuthTokens } from '../utils/types'; -import { getRegion } from '../utils/clients/CognitoIdentityProvider/utils'; +import { getRegionFromUserPoolId } from '../../../foundation/parsers'; import { toAttributeType } from '../utils/apiHelpers'; -import { CodeDeliveryDetailsType } from '../utils/clients/CognitoIdentityProvider/types'; +import { CodeDeliveryDetailsType } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider/types'; import { UpdateUserAttributesException } from '../types/errors'; import { getAuthUserAgentValue } from '../../../utils'; +import { createUpdateUserAttributesClient } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../factories'; /** * Updates user's attributes while authenticated. @@ -39,11 +40,17 @@ export const updateUserAttributes = async ( const authConfig = Amplify.getConfig().Auth?.Cognito; const clientMetadata = options?.clientMetadata; assertTokenProviderConfig(authConfig); + const { userPoolEndpoint, userPoolId } = authConfig; const { tokens } = await fetchAuthSession({ forceRefresh: false }); assertAuthTokens(tokens); + const updateUserAttributesClient = createUpdateUserAttributesClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); const { CodeDeliveryDetailsList } = await updateUserAttributesClient( { - region: getRegion(authConfig.userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.UpdateUserAttributes), }, { diff --git a/packages/auth/src/providers/cognito/apis/verifyTOTPSetup.ts b/packages/auth/src/providers/cognito/apis/verifyTOTPSetup.ts index 66c68fe9690..c5c1212c194 100644 --- a/packages/auth/src/providers/cognito/apis/verifyTOTPSetup.ts +++ b/packages/auth/src/providers/cognito/apis/verifyTOTPSetup.ts @@ -10,11 +10,12 @@ import { import { AuthValidationErrorCode } from '../../../errors/types/validation'; import { assertValidationError } from '../../../errors/utils/assertValidationError'; import { VerifyTOTPSetupInput } from '../types'; -import { verifySoftwareToken } from '../utils/clients/CognitoIdentityProvider'; import { VerifySoftwareTokenException } from '../types/errors'; -import { getRegion } from '../utils/clients/CognitoIdentityProvider/utils'; +import { getRegionFromUserPoolId } from '../../../foundation/parsers'; import { assertAuthTokens } from '../utils/types'; import { getAuthUserAgentValue } from '../../../utils'; +import { createVerifySoftwareTokenClient } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../factories'; /** * Verifies an OTP code retrieved from an associated authentication app. @@ -31,6 +32,7 @@ export async function verifyTOTPSetup( ): Promise { const authConfig = Amplify.getConfig().Auth?.Cognito; assertTokenProviderConfig(authConfig); + const { userPoolEndpoint, userPoolId } = authConfig; const { code, options } = input; assertValidationError( !!code, @@ -38,9 +40,14 @@ export async function verifyTOTPSetup( ); const { tokens } = await fetchAuthSession({ forceRefresh: false }); assertAuthTokens(tokens); + const verifySoftwareToken = createVerifySoftwareTokenClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); await verifySoftwareToken( { - region: getRegion(authConfig.userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.VerifyTOTPSetup), }, { diff --git a/packages/auth/src/providers/cognito/credentialsProvider/IdentityIdProvider.ts b/packages/auth/src/providers/cognito/credentialsProvider/IdentityIdProvider.ts index 4a8614a3db0..b96adf08fbc 100644 --- a/packages/auth/src/providers/cognito/credentialsProvider/IdentityIdProvider.ts +++ b/packages/auth/src/providers/cognito/credentialsProvider/IdentityIdProvider.ts @@ -5,7 +5,7 @@ import { AuthTokens, ConsoleLogger, Identity, getId } from '@aws-amplify/core'; import { CognitoIdentityPoolConfig } from '@aws-amplify/core/internals/utils'; import { AuthError } from '../../../errors/AuthError'; -import { getRegionFromIdentityPoolId } from '../utils/clients/CognitoIdentityProvider/utils'; +import { getRegionFromIdentityPoolId } from '../../../foundation/parsers'; import { GetIdException } from '../types/errors'; import { IdentityIdStore } from './types'; diff --git a/packages/auth/src/providers/cognito/credentialsProvider/credentialsProvider.ts b/packages/auth/src/providers/cognito/credentialsProvider/credentialsProvider.ts index fd02d349513..6356ff0fd09 100644 --- a/packages/auth/src/providers/cognito/credentialsProvider/credentialsProvider.ts +++ b/packages/auth/src/providers/cognito/credentialsProvider/credentialsProvider.ts @@ -15,7 +15,7 @@ import { } from '@aws-amplify/core/internals/utils'; import { AuthError } from '../../../errors/AuthError'; -import { getRegionFromIdentityPoolId } from '../utils/clients/CognitoIdentityProvider/utils'; +import { getRegionFromIdentityPoolId } from '../../../foundation/parsers'; import { assertIdTokenInAuthTokens } from '../utils/types'; import { IdentityIdStore } from './types'; diff --git a/packages/auth/src/providers/cognito/factories/createCognitoUserPoolEndpointResolver.ts b/packages/auth/src/providers/cognito/factories/createCognitoUserPoolEndpointResolver.ts new file mode 100644 index 00000000000..42a5b979402 --- /dev/null +++ b/packages/auth/src/providers/cognito/factories/createCognitoUserPoolEndpointResolver.ts @@ -0,0 +1,16 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { EndpointResolverOptions } from '@aws-amplify/core/internals/aws-client-utils'; +import { AmplifyUrl } from '@aws-amplify/core/internals/utils'; + +import { cognitoUserPoolEndpointResolver } from '../../../foundation/cognitoUserPoolEndpointResolver'; + +export const createCognitoUserPoolEndpointResolver = + ({ endpointOverride }: { endpointOverride: string | undefined }) => + (input: EndpointResolverOptions): { url: URL } => { + if (endpointOverride) { + return { url: new AmplifyUrl(endpointOverride) }; + } + + return cognitoUserPoolEndpointResolver(input); + }; diff --git a/packages/auth/src/providers/cognito/factories/index.ts b/packages/auth/src/providers/cognito/factories/index.ts new file mode 100644 index 00000000000..7f8050064d3 --- /dev/null +++ b/packages/auth/src/providers/cognito/factories/index.ts @@ -0,0 +1,3 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +export { createCognitoUserPoolEndpointResolver } from './createCognitoUserPoolEndpointResolver'; diff --git a/packages/auth/src/providers/cognito/tokenProvider/cacheTokens.ts b/packages/auth/src/providers/cognito/tokenProvider/cacheTokens.ts index 198ec6c4283..0be44aeb697 100644 --- a/packages/auth/src/providers/cognito/tokenProvider/cacheTokens.ts +++ b/packages/auth/src/providers/cognito/tokenProvider/cacheTokens.ts @@ -3,7 +3,7 @@ import { AmplifyError, decodeJWT } from '@aws-amplify/core/internals/utils'; import { CognitoAuthSignInDetails } from '../types'; -import { AuthenticationResultType } from '../utils/clients/CognitoIdentityProvider/types'; +import { AuthenticationResultType } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider/types'; import { tokenOrchestrator } from './tokenProvider'; import { CognitoAuthTokens, DeviceMetadata } from './types'; diff --git a/packages/auth/src/providers/cognito/utils/apiHelpers.ts b/packages/auth/src/providers/cognito/utils/apiHelpers.ts index 5ddd544513c..70da22165a5 100644 --- a/packages/auth/src/providers/cognito/utils/apiHelpers.ts +++ b/packages/auth/src/providers/cognito/utils/apiHelpers.ts @@ -2,8 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { AuthUserAttributes } from '../../../types'; - -import { AttributeType } from './clients/CognitoIdentityProvider/types'; +import { AttributeType } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider/types'; /** * Transforms a user attributes object into an array of AttributeType objects. diff --git a/packages/auth/src/providers/cognito/utils/clients/CognitoIdentityProvider/base.ts b/packages/auth/src/providers/cognito/utils/clients/CognitoIdentityProvider/base.ts deleted file mode 100644 index cff58009b87..00000000000 --- a/packages/auth/src/providers/cognito/utils/clients/CognitoIdentityProvider/base.ts +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -import { Amplify } from '@aws-amplify/core'; -import { - Endpoint, - EndpointResolverOptions, - Headers, - HttpRequest, - HttpResponse, - Middleware, - getDnsSuffix, - getRetryDecider, - jitteredBackoff, - parseJsonError, - unauthenticatedHandler, -} from '@aws-amplify/core/internals/aws-client-utils'; -import { - AmplifyUrl, - getAmplifyUserAgent, -} from '@aws-amplify/core/internals/utils'; -import { composeTransferHandler } from '@aws-amplify/core/internals/aws-client-utils/composers'; - -/** - * The service name used to sign requests if the API requires authentication. - */ -const SERVICE_NAME = 'cognito-idp'; - -/** - * The endpoint resolver function that returns the endpoint URL for a given region. - */ -const endpointResolver = ({ region }: EndpointResolverOptions) => { - const authConfig = Amplify.getConfig().Auth?.Cognito; - const customURL = authConfig?.userPoolEndpoint; - const defaultURL = new AmplifyUrl( - `https://${SERVICE_NAME}.${region}.${getDnsSuffix(region)}`, - ); - - return { - url: customURL ? new AmplifyUrl(customURL) : defaultURL, - }; -}; - -/** - * A Cognito Identity-specific middleware that disables caching for all requests. - */ -const disableCacheMiddlewareFactory: Middleware< - HttpRequest, - HttpResponse, - Record -> = () => (next, _) => - async function disableCacheMiddleware(request) { - request.headers['cache-control'] = 'no-store'; - - return next(request); - }; - -/** - * A Cognito Identity-specific transfer handler that does NOT sign requests, and - * disables caching. - * - * @internal - */ -export const cognitoUserPoolTransferHandler = composeTransferHandler< - [Parameters[0]], - HttpRequest, - HttpResponse, - typeof unauthenticatedHandler ->(unauthenticatedHandler, [disableCacheMiddlewareFactory]); - -/** - * @internal - */ -export const defaultConfig = { - service: SERVICE_NAME, - endpointResolver, - retryDecider: getRetryDecider(parseJsonError), - computeDelay: jitteredBackoff, - userAgentValue: getAmplifyUserAgent(), - cache: 'no-store', -}; - -/** - * @internal - */ -export const getSharedHeaders = (operation: string): Headers => ({ - 'content-type': 'application/x-amz-json-1.1', - 'x-amz-target': `AWSCognitoIdentityProviderService.${operation}`, -}); - -/** - * @internal - */ -export const buildHttpRpcRequest = ( - { url }: Endpoint, - headers: Headers, - body: string, -): HttpRequest => ({ - headers, - url, - body, - method: 'POST', -}); diff --git a/packages/auth/src/providers/cognito/utils/clients/CognitoIdentityProvider/index.ts b/packages/auth/src/providers/cognito/utils/clients/CognitoIdentityProvider/index.ts deleted file mode 100644 index 4ea8c01b599..00000000000 --- a/packages/auth/src/providers/cognito/utils/clients/CognitoIdentityProvider/index.ts +++ /dev/null @@ -1,286 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 -import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; -import { - Endpoint, - HttpRequest, - HttpResponse, - parseJsonBody, - parseJsonError, -} from '@aws-amplify/core/internals/aws-client-utils'; - -import { assertServiceError } from '../../../../../errors/utils/assertServiceError'; -import { AuthError } from '../../../../../errors/AuthError'; - -import { - buildHttpRpcRequest, - cognitoUserPoolTransferHandler, - defaultConfig, - getSharedHeaders, -} from './base'; -import type { - AssociateSoftwareTokenCommandInput as AssociateSoftwareTokenInput, - AssociateSoftwareTokenCommandOutput as AssociateSoftwareTokenOutput, - ChangePasswordCommandInput as ChangePasswordInput, - ChangePasswordCommandOutput as ChangePasswordOutput, - ConfirmDeviceCommandInput as ConfirmDeviceInput, - ConfirmDeviceCommandOutput as ConfirmDeviceOutput, - ConfirmForgotPasswordCommandInput as ConfirmForgotPasswordInput, - ConfirmForgotPasswordCommandOutput as ConfirmForgotPasswordOutput, - ConfirmSignUpCommandInput as ConfirmSignUpInput, - ConfirmSignUpCommandOutput as ConfirmSignUpOutput, - DeleteUserAttributesCommandInput as DeleteUserAttributesInput, - DeleteUserAttributesCommandOutput as DeleteUserAttributesOutput, - DeleteUserCommandInput as DeleteUserInput, - DeleteUserCommandOutput as DeleteUserOutput, - ForgetDeviceCommandInput as ForgetDeviceInput, - ForgetDeviceCommandOutput as ForgetDeviceOutput, - ForgotPasswordCommandInput as ForgotPasswordInput, - ForgotPasswordCommandOutput as ForgotPasswordOutput, - GetUserAttributeVerificationCodeCommandInput as GetUserAttributeVerificationCodeInput, - GetUserAttributeVerificationCodeCommandOutput as GetUserAttributeVerificationCodeOutput, - GetUserCommandInput as GetUserInput, - GetUserCommandOutput as GetUserOutput, - GlobalSignOutCommandInput as GlobalSignOutInput, - GlobalSignOutCommandOutput as GlobalSignOutOutput, - InitiateAuthCommandInput as InitiateAuthInput, - InitiateAuthCommandOutput as InitiateAuthOutput, - ListDevicesCommandInput as ListDevicesInput, - ListDevicesCommandOutput as ListDevicesOutput, - ResendConfirmationCodeCommandInput as ResendConfirmationCodeInput, - ResendConfirmationCodeCommandOutput as ResendConfirmationCodeOutput, - RespondToAuthChallengeCommandInput as RespondToAuthChallengeInput, - RespondToAuthChallengeCommandOutput as RespondToAuthChallengeOutput, - SetUserMFAPreferenceCommandInput as SetUserMFAPreferenceInput, - SetUserMFAPreferenceCommandOutput as SetUserMFAPreferenceOutput, - SignUpCommandInput as SignUpInput, - SignUpCommandOutput as SignUpOutput, - UpdateDeviceStatusCommandInput as UpdateDeviceStatusInput, - UpdateDeviceStatusCommandOutput as UpdateDeviceStatusOutput, - UpdateUserAttributesCommandInput as UpdateUserAttributesInput, - UpdateUserAttributesCommandOutput as UpdateUserAttributesOutput, - VerifySoftwareTokenCommandInput as VerifySoftwareTokenInput, - VerifySoftwareTokenCommandOutput as VerifySoftwareTokenOutput, - VerifyUserAttributeCommandInput as VerifyUserAttributeInput, - VerifyUserAttributeCommandOutput as VerifyUserAttributeOutput, -} from './types'; - -interface RevokeTokenInput { - Token: string; - ClientId: string; -} - -type RevokeTokenOutput = Record; - -type ClientOperation = - | 'SignUp' - | 'ConfirmSignUp' - | 'ForgotPassword' - | 'ConfirmForgotPassword' - | 'InitiateAuth' - | 'RespondToAuthChallenge' - | 'ResendConfirmationCode' - | 'VerifySoftwareToken' - | 'AssociateSoftwareToken' - | 'SetUserMFAPreference' - | 'GetUser' - | 'ChangePassword' - | 'ConfirmDevice' - | 'ForgetDevice' - | 'DeleteUser' - | 'GetUserAttributeVerificationCode' - | 'GlobalSignOut' - | 'UpdateUserAttributes' - | 'VerifyUserAttribute' - | 'DeleteUserAttributes' - | 'UpdateDeviceStatus' - | 'ListDevices' - | 'RevokeToken'; - -const buildUserPoolSerializer = - (operation: ClientOperation) => - (input: Input, endpoint: Endpoint): HttpRequest => { - const headers = getSharedHeaders(operation); - const body = JSON.stringify(input); - - return buildHttpRpcRequest(endpoint, headers, body); - }; - -const buildUserPoolDeserializer = (): (( - response: HttpResponse, -) => Promise) => { - return async (response: HttpResponse): Promise => { - if (response.statusCode >= 300) { - const error = await parseJsonError(response); - assertServiceError(error); - throw new AuthError({ name: error.name, message: error.message }); - } else { - const body = await parseJsonBody(response); - - return body; - } - }; -}; - -const handleEmptyResponseDeserializer = (): (( - response: HttpResponse, -) => Promise) => { - return async (response: HttpResponse): Promise => { - if (response.statusCode >= 300) { - const error = await parseJsonError(response); - assertServiceError(error); - throw new AuthError({ name: error.name, message: error.message }); - } else { - return undefined as any; - } - }; -}; - -export const initiateAuth = composeServiceApi( - cognitoUserPoolTransferHandler, - buildUserPoolSerializer('InitiateAuth'), - buildUserPoolDeserializer(), - defaultConfig, -); - -export const revokeToken = composeServiceApi( - cognitoUserPoolTransferHandler, - buildUserPoolSerializer('RevokeToken'), - buildUserPoolDeserializer(), - defaultConfig, -); - -export const signUp = composeServiceApi( - cognitoUserPoolTransferHandler, - buildUserPoolSerializer('SignUp'), - buildUserPoolDeserializer(), - defaultConfig, -); -export const confirmSignUp = composeServiceApi( - cognitoUserPoolTransferHandler, - buildUserPoolSerializer('ConfirmSignUp'), - buildUserPoolDeserializer(), - defaultConfig, -); -export const forgotPassword = composeServiceApi( - cognitoUserPoolTransferHandler, - buildUserPoolSerializer('ForgotPassword'), - buildUserPoolDeserializer(), - defaultConfig, -); -export const confirmForgotPassword = composeServiceApi( - cognitoUserPoolTransferHandler, - buildUserPoolSerializer('ConfirmForgotPassword'), - buildUserPoolDeserializer(), - defaultConfig, -); -export const respondToAuthChallenge = composeServiceApi( - cognitoUserPoolTransferHandler, - buildUserPoolSerializer( - 'RespondToAuthChallenge', - ), - buildUserPoolDeserializer(), - defaultConfig, -); -export const resendConfirmationCode = composeServiceApi( - cognitoUserPoolTransferHandler, - buildUserPoolSerializer( - 'ResendConfirmationCode', - ), - buildUserPoolDeserializer(), - defaultConfig, -); -export const verifySoftwareToken = composeServiceApi( - cognitoUserPoolTransferHandler, - buildUserPoolSerializer('VerifySoftwareToken'), - buildUserPoolDeserializer(), - defaultConfig, -); -export const associateSoftwareToken = composeServiceApi( - cognitoUserPoolTransferHandler, - buildUserPoolSerializer( - 'AssociateSoftwareToken', - ), - buildUserPoolDeserializer(), - defaultConfig, -); -export const setUserMFAPreference = composeServiceApi( - cognitoUserPoolTransferHandler, - buildUserPoolSerializer('SetUserMFAPreference'), - buildUserPoolDeserializer(), - defaultConfig, -); -export const getUser = composeServiceApi( - cognitoUserPoolTransferHandler, - buildUserPoolSerializer('GetUser'), - buildUserPoolDeserializer(), - defaultConfig, -); -export const changePassword = composeServiceApi( - cognitoUserPoolTransferHandler, - buildUserPoolSerializer('ChangePassword'), - buildUserPoolDeserializer(), - defaultConfig, -); -export const confirmDevice = composeServiceApi( - cognitoUserPoolTransferHandler, - buildUserPoolSerializer('ConfirmDevice'), - buildUserPoolDeserializer(), - defaultConfig, -); -export const forgetDevice = composeServiceApi( - cognitoUserPoolTransferHandler, - buildUserPoolSerializer('ForgetDevice'), - handleEmptyResponseDeserializer(), - defaultConfig, -); -export const deleteUser = composeServiceApi( - cognitoUserPoolTransferHandler, - buildUserPoolSerializer('DeleteUser'), - handleEmptyResponseDeserializer(), - defaultConfig, -); -export const getUserAttributeVerificationCode = composeServiceApi( - cognitoUserPoolTransferHandler, - buildUserPoolSerializer( - 'GetUserAttributeVerificationCode', - ), - buildUserPoolDeserializer(), - defaultConfig, -); -export const globalSignOut = composeServiceApi( - cognitoUserPoolTransferHandler, - buildUserPoolSerializer('GlobalSignOut'), - buildUserPoolDeserializer(), - defaultConfig, -); -export const updateUserAttributes = composeServiceApi( - cognitoUserPoolTransferHandler, - buildUserPoolSerializer('UpdateUserAttributes'), - buildUserPoolDeserializer(), - defaultConfig, -); -export const verifyUserAttribute = composeServiceApi( - cognitoUserPoolTransferHandler, - buildUserPoolSerializer('VerifyUserAttribute'), - buildUserPoolDeserializer(), - defaultConfig, -); -export const updateDeviceStatus = composeServiceApi( - cognitoUserPoolTransferHandler, - buildUserPoolSerializer('UpdateDeviceStatus'), - buildUserPoolDeserializer(), - defaultConfig, -); -export const listDevices = composeServiceApi( - cognitoUserPoolTransferHandler, - buildUserPoolSerializer('ListDevices'), - buildUserPoolDeserializer(), - defaultConfig, -); -export const deleteUserAttributes = composeServiceApi( - cognitoUserPoolTransferHandler, - buildUserPoolSerializer('DeleteUserAttributes'), - buildUserPoolDeserializer(), - defaultConfig, -); diff --git a/packages/auth/src/providers/cognito/utils/clients/base.ts b/packages/auth/src/providers/cognito/utils/clients/base.ts deleted file mode 100644 index a6a5fb6aca0..00000000000 --- a/packages/auth/src/providers/cognito/utils/clients/base.ts +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -import { - Endpoint, - EndpointResolverOptions, - Headers, - HttpRequest, - HttpResponse, - Middleware, - getDnsSuffix, - getRetryDecider, - jitteredBackoff, - parseJsonError, - unauthenticatedHandler, -} from '@aws-amplify/core/internals/aws-client-utils'; -import { - AmplifyUrl, - getAmplifyUserAgent, -} from '@aws-amplify/core/internals/utils'; -import { composeTransferHandler } from '@aws-amplify/core/internals/aws-client-utils/composers'; - -/** - * The service name used to sign requests if the API requires authentication. - */ -const SERVICE_NAME = 'cognito-idp'; - -/** - * The endpoint resolver function that returns the endpoint URL for a given region. - */ -const endpointResolver = ({ region }: EndpointResolverOptions) => ({ - url: new AmplifyUrl( - `https://${SERVICE_NAME}.${region}.${getDnsSuffix(region)}`, - ), -}); - -/** - * A Cognito Identity-specific middleware that disables caching for all requests. - */ -const disableCacheMiddlewareFactory: Middleware< - HttpRequest, - HttpResponse, - Record -> = () => (next, _) => - async function disableCacheMiddleware(request) { - request.headers['cache-control'] = 'no-store'; - - return next(request); - }; - -/** - * A Cognito Identity-specific transfer handler that does NOT sign requests, and - * disables caching. - * - * @internal - */ -export const cognitoUserPoolTransferHandler = composeTransferHandler< - [Parameters[0]], - HttpRequest, - HttpResponse, - typeof unauthenticatedHandler ->(unauthenticatedHandler, [disableCacheMiddlewareFactory]); - -/** - * @internal - */ -export const defaultConfig = { - service: SERVICE_NAME, - endpointResolver, - retryDecider: getRetryDecider(parseJsonError), - computeDelay: jitteredBackoff, - userAgentValue: getAmplifyUserAgent(), -}; - -/** - * @internal - */ -export const getSharedHeaders = (operation: string): Headers => ({ - 'content-type': 'application/x-amz-json-1.1', - 'x-amz-target': `AWSCognitoIdentityProviderService.${operation}`, -}); - -/** - * @internal - */ -export const buildHttpRpcRequest = ( - { url }: Endpoint, - headers: Headers, - body: any, -): HttpRequest => ({ - headers, - url, - body, - method: 'POST', -}); diff --git a/packages/auth/src/providers/cognito/utils/refreshAuthTokens.ts b/packages/auth/src/providers/cognito/utils/refreshAuthTokens.ts index 6c3df620492..01f35a40b2b 100644 --- a/packages/auth/src/providers/cognito/utils/refreshAuthTokens.ts +++ b/packages/auth/src/providers/cognito/utils/refreshAuthTokens.ts @@ -9,10 +9,11 @@ import { } from '@aws-amplify/core/internals/utils'; import { CognitoAuthTokens, TokenRefresher } from '../tokenProvider/types'; -import { initiateAuth } from '../utils/clients/CognitoIdentityProvider'; -import { getRegion } from '../utils/clients/CognitoIdentityProvider/utils'; +import { getRegionFromUserPoolId } from '../../../foundation/parsers'; import { assertAuthTokensWithRefreshToken } from '../utils/types'; import { AuthError } from '../../../errors/AuthError'; +import { createInitiateAuthClient } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../factories'; import { getUserContextData } from './userContextData'; @@ -26,7 +27,8 @@ const refreshAuthTokensFunction: TokenRefresher = async ({ username: string; }): Promise => { assertTokenProviderConfig(authConfig?.Cognito); - const region = getRegion(authConfig.Cognito.userPoolId); + const { userPoolId, userPoolClientId, userPoolEndpoint } = authConfig.Cognito; + const region = getRegionFromUserPoolId(userPoolId); assertAuthTokensWithRefreshToken(tokens); const refreshTokenString = tokens.refreshToken; @@ -39,14 +41,20 @@ const refreshAuthTokensFunction: TokenRefresher = async ({ const UserContextData = getUserContextData({ username, - userPoolId: authConfig.Cognito.userPoolId, - userPoolClientId: authConfig.Cognito.userPoolClientId, + userPoolId, + userPoolClientId, + }); + + const initiateAuth = createInitiateAuthClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), }); const { AuthenticationResult } = await initiateAuth( { region }, { - ClientId: authConfig?.Cognito?.userPoolClientId, + ClientId: userPoolClientId, AuthFlow: 'REFRESH_TOKEN_AUTH', AuthParameters, UserContextData, diff --git a/packages/auth/src/providers/cognito/utils/signInHelpers.ts b/packages/auth/src/providers/cognito/utils/signInHelpers.ts index 13edcd84e62..ef4c1422bf3 100644 --- a/packages/auth/src/providers/cognito/utils/signInHelpers.ts +++ b/packages/auth/src/providers/cognito/utils/signInHelpers.ts @@ -31,15 +31,14 @@ import { USER_ALREADY_AUTHENTICATED_EXCEPTION } from '../../../errors/constants' import { getCurrentUser } from '../apis/getCurrentUser'; import { AuthTokenOrchestrator, DeviceMetadata } from '../tokenProvider/types'; import { getAuthUserAgentValue } from '../../../utils'; - -import { signInStore } from './signInStore'; import { - associateSoftwareToken, - confirmDevice, - initiateAuth, - respondToAuthChallenge, - verifySoftwareToken, -} from './clients/CognitoIdentityProvider'; + createAssociateSoftwareTokenClient, + createConfirmDeviceClient, + createInitiateAuthClient, + createRespondToAuthChallengeClient, + createVerifySoftwareTokenClient, +} from '../../../foundation/factories/serviceClients/cognitoIdentityProvider'; +import { createCognitoUserPoolEndpointResolver } from '../factories'; import { ChallengeName, ChallengeParameters, @@ -49,8 +48,10 @@ import { NewDeviceMetadataType, RespondToAuthChallengeCommandInput, RespondToAuthChallengeCommandOutput, -} from './clients/CognitoIdentityProvider/types'; -import { getRegion } from './clients/CognitoIdentityProvider/utils'; +} from '../../../foundation/factories/serviceClients/cognitoIdentityProvider/types'; +import { getRegionFromUserPoolId } from '../../../foundation/parsers'; + +import { signInStore } from './signInStore'; import { assertDeviceMetadata } from './types'; import { getAuthenticationHelper, @@ -92,7 +93,7 @@ export async function handleCustomChallenge({ }: HandleAuthChallengeRequest & { tokenOrchestrator: AuthTokenOrchestrator; }): Promise { - const { userPoolId, userPoolClientId } = config; + const { userPoolId, userPoolClientId, userPoolEndpoint } = config; const challengeResponses: Record = { USERNAME: username, ANSWER: challengeResponse, @@ -118,9 +119,14 @@ export async function handleCustomChallenge({ UserContextData, }; + const respondToAuthChallenge = createRespondToAuthChallengeClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); const response = await respondToAuthChallenge( { - region: getRegion(userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.ConfirmSignIn), }, jsonReq, @@ -147,14 +153,18 @@ export async function handleMFASetupChallenge({ deviceName, config, }: HandleAuthChallengeRequest): Promise { - const { userPoolId, userPoolClientId } = config; + const { userPoolId, userPoolClientId, userPoolEndpoint } = config; const challengeResponses = { USERNAME: username, }; - + const verifySoftwareToken = createVerifySoftwareTokenClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); const { Session } = await verifySoftwareToken( { - region: getRegion(userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.ConfirmSignIn), }, { @@ -177,7 +187,16 @@ export async function handleMFASetupChallenge({ ClientId: userPoolClientId, }; - return respondToAuthChallenge({ region: getRegion(userPoolId) }, jsonReq); + const respondToAuthChallenge = createRespondToAuthChallengeClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); + + return respondToAuthChallenge( + { region: getRegionFromUserPoolId(userPoolId) }, + jsonReq, + ); } export async function handleSelectMFATypeChallenge({ @@ -187,7 +206,7 @@ export async function handleSelectMFATypeChallenge({ session, config, }: HandleAuthChallengeRequest): Promise { - const { userPoolId, userPoolClientId } = config; + const { userPoolId, userPoolClientId, userPoolEndpoint } = config; assertValidationError( challengeResponse === 'TOTP' || challengeResponse === 'SMS', AuthValidationErrorCode.IncorrectMFAMethod, @@ -213,9 +232,15 @@ export async function handleSelectMFATypeChallenge({ UserContextData, }; + const respondToAuthChallenge = createRespondToAuthChallengeClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); + return respondToAuthChallenge( { - region: getRegion(userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.ConfirmSignIn), }, jsonReq, @@ -229,7 +254,7 @@ export async function handleSMSMFAChallenge({ username, config, }: HandleAuthChallengeRequest): Promise { - const { userPoolId, userPoolClientId } = config; + const { userPoolId, userPoolClientId, userPoolEndpoint } = config; const challengeResponses = { USERNAME: username, SMS_MFA_CODE: challengeResponse, @@ -248,9 +273,15 @@ export async function handleSMSMFAChallenge({ UserContextData, }; + const respondToAuthChallenge = createRespondToAuthChallengeClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); + return respondToAuthChallenge( { - region: getRegion(userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.ConfirmSignIn), }, jsonReq, @@ -263,7 +294,7 @@ export async function handleSoftwareTokenMFAChallenge({ username, config, }: HandleAuthChallengeRequest): Promise { - const { userPoolId, userPoolClientId } = config; + const { userPoolId, userPoolClientId, userPoolEndpoint } = config; const challengeResponses = { USERNAME: username, SOFTWARE_TOKEN_MFA_CODE: challengeResponse, @@ -284,9 +315,15 @@ export async function handleSoftwareTokenMFAChallenge({ UserContextData, }; + const respondToAuthChallenge = createRespondToAuthChallengeClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); + return respondToAuthChallenge( { - region: getRegion(userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.ConfirmSignIn), }, jsonReq, @@ -300,7 +337,7 @@ export async function handleCompleteNewPasswordChallenge({ requiredAttributes, config, }: HandleAuthChallengeRequest): Promise { - const { userPoolId, userPoolClientId } = config; + const { userPoolId, userPoolClientId, userPoolEndpoint } = config; const challengeResponses = { ...createAttributes(requiredAttributes), NEW_PASSWORD: challengeResponse, @@ -322,9 +359,15 @@ export async function handleCompleteNewPasswordChallenge({ UserContextData, }; + const respondToAuthChallenge = createRespondToAuthChallengeClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); + return respondToAuthChallenge( { - region: getRegion(userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.ConfirmSignIn), }, jsonReq, @@ -338,7 +381,7 @@ export async function handleUserPasswordAuthFlow( config: CognitoUserPoolConfig, tokenOrchestrator: AuthTokenOrchestrator, ): Promise { - const { userPoolClientId, userPoolId } = config; + const { userPoolClientId, userPoolId, userPoolEndpoint } = config; const authParameters: Record = { USERNAME: username, PASSWORD: password, @@ -363,9 +406,15 @@ export async function handleUserPasswordAuthFlow( UserContextData, }; + const initiateAuth = createInitiateAuthClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); + const response = await initiateAuth( { - region: getRegion(userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.SignIn), }, jsonReq, @@ -397,7 +446,7 @@ export async function handleUserSRPAuthFlow( config: CognitoUserPoolConfig, tokenOrchestrator: AuthTokenOrchestrator, ): Promise { - const { userPoolId, userPoolClientId } = config; + const { userPoolId, userPoolClientId, userPoolEndpoint } = config; const userPoolName = userPoolId?.split('_')[1] || ''; const authenticationHelper = await getAuthenticationHelper(userPoolName); @@ -420,9 +469,15 @@ export async function handleUserSRPAuthFlow( UserContextData, }; + const initiateAuth = createInitiateAuthClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); + const resp = await initiateAuth( { - region: getRegion(userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.SignIn), }, jsonReq, @@ -453,7 +508,7 @@ export async function handleCustomAuthFlowWithoutSRP( config: CognitoUserPoolConfig, tokenOrchestrator: AuthTokenOrchestrator, ): Promise { - const { userPoolClientId, userPoolId } = config; + const { userPoolClientId, userPoolId, userPoolEndpoint } = config; const authParameters: Record = { USERNAME: username, }; @@ -477,9 +532,15 @@ export async function handleCustomAuthFlowWithoutSRP( UserContextData, }; + const initiateAuth = createInitiateAuthClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); + const response = await initiateAuth( { - region: getRegion(userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.SignIn), }, jsonReq, @@ -506,7 +567,7 @@ export async function handleCustomSRPAuthFlow( tokenOrchestrator: AuthTokenOrchestrator, ) { assertTokenProviderConfig(config); - const { userPoolId, userPoolClientId } = config; + const { userPoolId, userPoolClientId, userPoolEndpoint } = config; const userPoolName = userPoolId?.split('_')[1] || ''; const authenticationHelper = await getAuthenticationHelper(userPoolName); @@ -531,10 +592,16 @@ export async function handleCustomSRPAuthFlow( UserContextData, }; + const initiateAuth = createInitiateAuthClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); + const { ChallengeParameters: challengeParameters, Session: session } = await initiateAuth( { - region: getRegion(userPoolId), + region: getRegionFromUserPoolId(userPoolId), userAgentValue: getAuthUserAgentValue(AuthAction.SignIn), }, jsonReq, @@ -565,7 +632,7 @@ async function handleDeviceSRPAuth({ session, tokenOrchestrator, }: HandleDeviceSRPInput): Promise { - const { userPoolId } = config; + const { userPoolId, userPoolEndpoint } = config; const clientId = config.userPoolClientId; const deviceMetadata = await tokenOrchestrator?.getDeviceMetadata(username); assertDeviceMetadata(deviceMetadata); @@ -585,9 +652,14 @@ async function handleDeviceSRPAuth({ ClientMetadata: clientMetadata, Session: session, }; + const respondToAuthChallenge = createRespondToAuthChallengeClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); const { ChallengeParameters: respondedChallengeParameters, Session } = await respondToAuthChallenge( - { region: getRegion(userPoolId) }, + { region: getRegionFromUserPoolId(userPoolId) }, jsonReqResponseChallenge, ); @@ -608,7 +680,7 @@ async function handleDevicePasswordVerifier( clientMetadata: ClientMetadata | undefined, session: string | undefined, authenticationHelper: AuthenticationHelper, - { userPoolId, userPoolClientId }: CognitoUserPoolConfig, + { userPoolId, userPoolClientId, userPoolEndpoint }: CognitoUserPoolConfig, tokenOrchestrator?: AuthTokenOrchestrator, ): Promise { const deviceMetadata = await tokenOrchestrator?.getDeviceMetadata(username); @@ -654,9 +726,14 @@ async function handleDevicePasswordVerifier( ClientMetadata: clientMetadata, UserContextData, }; + const respondToAuthChallenge = createRespondToAuthChallengeClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); return respondToAuthChallenge( - { region: getRegion(userPoolId) }, + { region: getRegionFromUserPoolId(userPoolId) }, jsonReqResponseChallenge, ); } @@ -670,7 +747,7 @@ export async function handlePasswordVerifierChallenge( config: CognitoUserPoolConfig, tokenOrchestrator: AuthTokenOrchestrator, ): Promise { - const { userPoolId, userPoolClientId } = config; + const { userPoolId, userPoolClientId, userPoolEndpoint } = config; const userPoolName = userPoolId?.split('_')[1] || ''; const serverBValue = new (BigInteger as any)(challengeParameters?.SRP_B, 16); const salt = new (BigInteger as any)(challengeParameters?.SALT, 16); @@ -722,8 +799,14 @@ export async function handlePasswordVerifierChallenge( UserContextData, }; + const respondToAuthChallenge = createRespondToAuthChallengeClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); + const response = await respondToAuthChallenge( - { region: getRegion(userPoolId) }, + { region: getRegionFromUserPoolId(userPoolId) }, jsonReqResponseChallenge, ); @@ -766,8 +849,14 @@ export async function getSignInResult(params: { parseMFATypes(challengeParameters.MFAS_CAN_SETUP), )}`, }); + + const associateSoftwareToken = createAssociateSoftwareTokenClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: authConfig.userPoolEndpoint, + }), + }); const { Session, SecretCode: secretCode } = await associateSoftwareToken( - { region: getRegion(authConfig.userPoolId) }, + { region: getRegionFromUserPoolId(authConfig.userPoolId) }, { Session: signInSession, }, @@ -1037,11 +1126,17 @@ export async function assertUserNotAuthenticated() { * * @returns DeviceMetadata | undefined */ -export async function getNewDeviceMetatada( - userPoolId: string, - newDeviceMetadata?: NewDeviceMetadataType, - accessToken?: string, -): Promise { +export async function getNewDeviceMetadata({ + userPoolId, + userPoolEndpoint, + newDeviceMetadata, + accessToken, +}: { + userPoolId: string; + userPoolEndpoint: string | undefined; + newDeviceMetadata?: NewDeviceMetadataType; + accessToken?: string; +}): Promise { if (!newDeviceMetadata) return undefined; const userPoolName = userPoolId.split('_')[1] || ''; const authenticationHelper = await getAuthenticationHelper(userPoolName); @@ -1069,8 +1164,13 @@ export async function getNewDeviceMetatada( const randomPassword = authenticationHelper.getRandomPassword(); try { + const confirmDevice = createConfirmDeviceClient({ + endpointResolver: createCognitoUserPoolEndpointResolver({ + endpointOverride: userPoolEndpoint, + }), + }); await confirmDevice( - { region: getRegion(userPoolId) }, + { region: getRegionFromUserPoolId(userPoolId) }, { AccessToken: accessToken, DeviceName: await getDeviceName(), diff --git a/packages/auth/src/providers/cognito/utils/signInStore.ts b/packages/auth/src/providers/cognito/utils/signInStore.ts index 0028ab71067..fd07cb15e6d 100644 --- a/packages/auth/src/providers/cognito/utils/signInStore.ts +++ b/packages/auth/src/providers/cognito/utils/signInStore.ts @@ -2,8 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { CognitoAuthSignInDetails } from '../types'; - -import { ChallengeName } from './clients/CognitoIdentityProvider/types'; +import { ChallengeName } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider/types'; // TODO: replace all of this implementation with state machines interface SignInState { diff --git a/packages/auth/src/providers/cognito/utils/signUpHelpers.ts b/packages/auth/src/providers/cognito/utils/signUpHelpers.ts index 73e59c78406..8ab2943ce2a 100644 --- a/packages/auth/src/providers/cognito/utils/signUpHelpers.ts +++ b/packages/auth/src/providers/cognito/utils/signUpHelpers.ts @@ -10,8 +10,7 @@ import { AutoSignInCallback } from '../../../types/models'; import { AuthError } from '../../../errors/AuthError'; import { resetAutoSignIn, setAutoSignIn } from '../apis/autoSignIn'; import { AUTO_SIGN_IN_EXCEPTION } from '../../../errors/constants'; - -import { SignUpCommandOutput } from './clients/CognitoIdentityProvider/types'; +import { SignUpCommandOutput } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider/types'; const MAX_AUTOSIGNIN_POLLING_MS = 3 * 60 * 1000; diff --git a/packages/aws-amplify/package.json b/packages/aws-amplify/package.json index ceb48b8fa23..23885357eb9 100644 --- a/packages/aws-amplify/package.json +++ b/packages/aws-amplify/package.json @@ -335,7 +335,7 @@ "name": "[API] generateClient (AppSync)", "path": "./dist/esm/api/index.mjs", "import": "{ generateClient }", - "limit": "41.5 kB" + "limit": "43.1 kB" }, { "name": "[API] REST API handlers", diff --git a/packages/core/__tests__/utils/globalHelpers/globalHelpers.test.ts b/packages/core/__tests__/utils/globalHelpers/globalHelpers.test.ts index 4d9dbd8bc17..bb7d2e39a9b 100644 --- a/packages/core/__tests__/utils/globalHelpers/globalHelpers.test.ts +++ b/packages/core/__tests__/utils/globalHelpers/globalHelpers.test.ts @@ -44,12 +44,6 @@ describe('getGlobal', () => { expect(getCrypto()).toEqual(mockCrypto); }); - - it('should throw error if crypto is unavailable globally', () => { - mockWindow.mockImplementation(() => undefined); - - expect(() => getCrypto()).toThrow(AmplifyError); - }); }); describe('getBtoa()', () => { diff --git a/packages/core/src/singleton/API/types.ts b/packages/core/src/singleton/API/types.ts index 20dd5bd3dfc..3909d264180 100644 --- a/packages/core/src/singleton/API/types.ts +++ b/packages/core/src/singleton/API/types.ts @@ -111,6 +111,8 @@ export interface ModelIntrospectionSchema { queries?: CustomOperations; mutations?: CustomOperations; subscriptions?: CustomOperations; + conversations?: SchemaConversationRoutes; + generations?: SchemaGenerationRoutes; } /** @@ -120,6 +122,27 @@ export type SchemaModels = Record; export type SchemaNonModels = Record; export type SchemaEnums = Record; export type CustomOperations = Record; +type SchemaConversationRoutes = Record; +type SchemaGenerationRoutes = Record; + +interface SchemaConversationRoute { + name: string; + models: SchemaModels; + nonModels: SchemaNonModels; + enums: SchemaEnums; + conversation: SchemaConversation; + message: SchemaConversationMessage; +} + +interface SchemaConversation { + modelName: string; +} + +interface SchemaConversationMessage { + modelName: string; + subscribe: CustomOperation; + send: CustomOperation; +} export interface SchemaModel { name: string; @@ -164,7 +187,7 @@ export type CustomOperationArguments = Record; export interface CustomOperationArgument { name: string; - type: FieldType; + type: InputFieldType; isArray: boolean; isRequired: boolean; isArrayNullable?: boolean; @@ -192,7 +215,15 @@ export interface NonModelFieldType { nonModel: string; } -export type FieldType = +interface EnumType { + enum: string; +} + +interface InputType { + input: string; +} + +type ScalarType = | 'ID' | 'String' | 'Int' @@ -206,10 +237,12 @@ export type FieldType = | 'AWSIPAddress' | 'Boolean' | 'AWSJSON' - | 'AWSPhone' - | { enum: string } - | ModelFieldType - | NonModelFieldType; + | 'AWSPhone'; + +type FieldType = ScalarType | EnumType | ModelFieldType | NonModelFieldType; + +type InputFieldType = ScalarType | EnumType | InputType; + export type FieldAttribute = ModelAttribute; /** diff --git a/packages/core/src/utils/globalHelpers/index.ts b/packages/core/src/utils/globalHelpers/index.ts index 622f4d3c3ef..dc35f897bf6 100644 --- a/packages/core/src/utils/globalHelpers/index.ts +++ b/packages/core/src/utils/globalHelpers/index.ts @@ -13,6 +13,16 @@ export const getCrypto = () => { return crypto; } + try { + const crypto = require('node:crypto').webcrypto; + + if (typeof crypto === 'object') { + return crypto; + } + } catch (_) { + // no-op + } + throw new AmplifyError({ name: 'MissingPolyfill', message: 'Cannot resolve the `crypto` function from the environment.', diff --git a/scripts/dts-bundler/dts-bundler.config.js b/scripts/dts-bundler/dts-bundler.config.js index 77671630aeb..90210b58cee 100644 --- a/scripts/dts-bundler/dts-bundler.config.js +++ b/scripts/dts-bundler/dts-bundler.config.js @@ -44,12 +44,15 @@ const authPackageSrcClientsPath = join( 'packages', 'auth', 'src', - 'providers', - 'cognito', - 'utils', - 'clients', + 'foundation', + 'factories', + 'serviceClients', + 'cognitoIdentityProvider', + 'types', ); +// packages/auth/src/foundation/factories/serviceClients/cognitoIdentityProvider/types/Sdk.ts + /** @type import('dts-bundle-generator/config-schema').BundlerConfig */ const config = { compilationOptions: { @@ -84,8 +87,7 @@ const config = { filePath: './cognito-identity-provider.d.ts', outFile: join( authPackageSrcClientsPath, - 'CognitoIdentityProvider', - 'types.ts', + 'Sdk.ts', ), libraries: { inlinedLibraries: ['@aws-sdk/client-cognito-identity-provider'], diff --git a/yarn.lock b/yarn.lock index e3e9b5f2400..68e83991cff 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18,13 +18,15 @@ graphql "15.8.0" rxjs "^7.8.1" -"@aws-amplify/data-schema@^1.0.0": - version "1.3.10" - resolved "https://registry.yarnpkg.com/@aws-amplify/data-schema/-/data-schema-1.3.10.tgz#e83ef1d8d11efb821b282e499c373f64f3bf60ae" - integrity sha512-rUo6wb+DO6aGCSeSiB8wb92O4cEuN4sZBXn7TgqaYc8Bv4HutrLaIlptgXCYJMkaAp/h9rxyi6wIFJ7bEyD/6g== +"@aws-amplify/data-schema@^1.5.0": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@aws-amplify/data-schema/-/data-schema-1.5.1.tgz#d9f2e263e10f7bd8dc9c1908a4ac0e795e581b7c" + integrity sha512-hFDqqwHqdoFazmvGOApCX8kqrdoum9YJikmAQN5tP2sgnCT++lqznFw2F4PPqDJRxhQP1AYuwhbbRBvGLMbs/w== dependencies: "@aws-amplify/data-schema-types" "*" + "@smithy/util-base64" "^3.0.0" "@types/aws-lambda" "^8.10.134" + "@types/json-schema" "^7.0.15" rxjs "^7.8.1" "@aws-crypto/crc32@3.0.0": @@ -5169,7 +5171,7 @@ "@types/tough-cookie" "*" parse5 "^7.0.0" -"@types/json-schema@*", "@types/json-schema@^7.0.12", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8": +"@types/json-schema@*", "@types/json-schema@^7.0.12", "@types/json-schema@^7.0.15", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== @@ -7513,6 +7515,11 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== +encodeurl@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" + integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== + encoding@^0.1.12, encoding@^0.1.13: version "0.1.13" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" @@ -14044,10 +14051,10 @@ semver@^7.0.0, semver@^7.1.1, semver@^7.1.3, semver@^7.3.4, semver@^7.3.5, semve resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== -send@0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" - integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== +send@0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" + integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw== dependencies: debug "2.6.9" depd "2.0.0" @@ -14076,14 +14083,14 @@ serialize-javascript@^6.0.1: randombytes "^2.1.0" serve-static@^1.13.1: - version "1.15.0" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" - integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + version "1.16.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296" + integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw== dependencies: - encodeurl "~1.0.2" + encodeurl "~2.0.0" escape-html "~1.0.3" parseurl "~1.3.3" - send "0.18.0" + send "0.19.0" set-blocking@^2.0.0: version "2.0.0" @@ -14505,7 +14512,16 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -14583,7 +14599,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -14597,6 +14613,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -15734,7 +15757,7 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -15761,6 +15784,15 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"