Skip to content

Commit

Permalink
chore(auth): improve error message on failure of getCurrentUser while…
Browse files Browse the repository at this point in the history
… dispatching signedIn event (#13019)

* chore(auth): improve error message on failure of getCurrentUser while dispatching signedIn event

* Apply suggestions from code review

Co-authored-by: Chris F <5827964+cshfang@users.noreply.github.com>

* Update test

* rebaseline bundle size (newly added error message)

---------

Co-authored-by: Chris F <5827964+cshfang@users.noreply.github.com>
  • Loading branch information
HuiSF and cshfang authored Feb 16, 2024
1 parent 1fdbb12 commit e4ae0f6
Show file tree
Hide file tree
Showing 10 changed files with 131 additions and 50 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import { Hub } from '@aws-amplify/core';
import { AMPLIFY_SYMBOL } from '@aws-amplify/core/internals/utils';
import {
dispatchSignedInHubEvent,
ERROR_MESSAGE,
} from '../../../../src/providers/cognito/utils/dispatchSignedInHubEvent';
import { getCurrentUser } from '../../../../src/providers/cognito/apis/getCurrentUser';
import { assertAuthTokens } from '../../../../src/providers/cognito/utils/types';

jest.mock('../../../../src/providers/cognito/apis/getCurrentUser', () => ({
getCurrentUser: jest.fn(),
}));
jest.mock('@aws-amplify/core', () => ({
Hub: {
dispatch: jest.fn(),
},
}));
jest.mock('@aws-amplify/core/internals/utils', () => ({
...jest.requireActual('@aws-amplify/core/internals/utils'),
AMPLIFY_SYMBOL: Symbol('AMPLIFY_SYMBOL'),
}));

const mockGetCurrentUser = getCurrentUser as jest.Mock;
const mockDispatch = Hub.dispatch as jest.Mock;

describe('dispatchSignedInHubEvent()', () => {
it('dispatches Hub event `signedIn` with `getCurrentUser()` returned data', async () => {
const mockGetCurrentUserPayload = {
username: 'hello',
userId: 'userId',
};
mockGetCurrentUser.mockResolvedValueOnce(mockGetCurrentUserPayload);

await dispatchSignedInHubEvent();

expect(mockDispatch).toHaveBeenCalledWith(
'auth',
{
event: 'signedIn',
data: mockGetCurrentUserPayload,
},
'Auth',
AMPLIFY_SYMBOL,
);
});

it('throws error when `getCurrentUser()` throws `USER_UNAUTHENTICATED_EXCEPTION`', () => {
mockGetCurrentUser.mockImplementationOnce(() => {
assertAuthTokens(null);
});

expect(() => dispatchSignedInHubEvent()).rejects.toThrow(ERROR_MESSAGE);
});

it('rethrows error if the error is not handled by itself', () => {
const mockError = new Error('some other error');

mockGetCurrentUser.mockImplementationOnce(() => {
throw mockError;
});

expect(() => dispatchSignedInHubEvent()).rejects.toThrow(mockError);
});
});
1 change: 1 addition & 0 deletions packages/auth/src/errors/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ export const invalidOriginException = new AuthError({
});
export const OAUTH_SIGNOUT_EXCEPTION = 'OAuthSignOutException';
export const TOKEN_REFRESH_EXCEPTION = 'TokenRefreshException';
export const UNEXPECTED_SIGN_IN_INTERRUPTION_EXCEPTION = 'UnexpectedSignInInterruptionException';
13 changes: 4 additions & 9 deletions packages/auth/src/providers/cognito/apis/confirmSignIn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
} from '../utils/clients/CognitoIdentityProvider/types';
import { tokenOrchestrator } from '../tokenProvider';
import { getCurrentUser } from './getCurrentUser';
import { dispatchSignedInHubEvent } from '../utils/dispatchSignedInHubEvent';

/**
* Continues or completes the sign in process when required by the initial call to `signIn`.
Expand Down Expand Up @@ -122,15 +123,9 @@ export async function confirmSignIn(
),
signInDetails,
});
Hub.dispatch(
'auth',
{
event: 'signedIn',
data: await getCurrentUser(),
},
'Auth',
AMPLIFY_SYMBOL,
);

await dispatchSignedInHubEvent();

return {
isSignedIn: true,
nextStep: { signInStep: 'DONE' },
Expand Down
10 changes: 4 additions & 6 deletions packages/auth/src/providers/cognito/apis/signInWithCustomAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
} from '../utils/clients/CognitoIdentityProvider/types';
import { tokenOrchestrator } from '../tokenProvider';
import { getCurrentUser } from './getCurrentUser';
import { dispatchSignedInHubEvent } from '../utils/dispatchSignedInHubEvent';

/**
* Signs a user in using a custom authentication flow without password
Expand Down Expand Up @@ -98,12 +99,9 @@ export async function signInWithCustomAuth(
),
signInDetails,
});
Hub.dispatch(
'auth',
{ event: 'signedIn', data: await getCurrentUser() },
'Auth',
AMPLIFY_SYMBOL,
);

await dispatchSignedInHubEvent();

return {
isSignedIn: true,
nextStep: { signInStep: 'DONE' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
} from '../utils/clients/CognitoIdentityProvider/types';
import { tokenOrchestrator } from '../tokenProvider';
import { getCurrentUser } from './getCurrentUser';
import { dispatchSignedInHubEvent } from '../utils/dispatchSignedInHubEvent';

/**
* Signs a user in using a custom authentication flow with SRP
Expand Down Expand Up @@ -102,15 +103,9 @@ export async function signInWithCustomSRPAuth(
signInDetails,
});
cleanActiveSignInState();
Hub.dispatch(
'auth',
{
event: 'signedIn',
data: await getCurrentUser(),
},
'Auth',
AMPLIFY_SYMBOL,
);

await dispatchSignedInHubEvent();

return {
isSignedIn: true,
nextStep: { signInStep: 'DONE' },
Expand Down
13 changes: 4 additions & 9 deletions packages/auth/src/providers/cognito/apis/signInWithSRP.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
import { cacheCognitoTokens } from '../tokenProvider/cacheTokens';
import { tokenOrchestrator } from '../tokenProvider';
import { getCurrentUser } from './getCurrentUser';
import { dispatchSignedInHubEvent } from '../utils/dispatchSignedInHubEvent';

/**
* Signs a user in
Expand Down Expand Up @@ -102,15 +103,9 @@ export async function signInWithSRP(
),
signInDetails,
});
Hub.dispatch(
'auth',
{
event: 'signedIn',
data: await getCurrentUser(),
},
'Auth',
AMPLIFY_SYMBOL,
);

await dispatchSignedInHubEvent();

return {
isSignedIn: true,
nextStep: { signInStep: 'DONE' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
import { cacheCognitoTokens } from '../tokenProvider/cacheTokens';
import { tokenOrchestrator } from '../tokenProvider';
import { getCurrentUser } from './getCurrentUser';
import { dispatchSignedInHubEvent } from '../utils/dispatchSignedInHubEvent';

/**
* Signs a user in using USER_PASSWORD_AUTH AuthFlowType
Expand Down Expand Up @@ -97,15 +98,9 @@ export async function signInWithUserPassword(
signInDetails,
});
cleanActiveSignInState();
Hub.dispatch(
'auth',
{
event: 'signedIn',
data: await getCurrentUser(),
},
'Auth',
AMPLIFY_SYMBOL,
);

await dispatchSignedInHubEvent();

return {
isSignedIn: true,
nextStep: { signInStep: 'DONE' },
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import { Hub } from '@aws-amplify/core';
import { getCurrentUser } from '../apis/getCurrentUser';
import { AMPLIFY_SYMBOL } from '@aws-amplify/core/internals/utils';
import {
UNEXPECTED_SIGN_IN_INTERRUPTION_EXCEPTION,
USER_UNAUTHENTICATED_EXCEPTION,
} from '../../../errors/constants';
import { AuthError } from '../../../errors/AuthError';

export const ERROR_MESSAGE =
'Unable to get user session following successful sign-in.';

export const dispatchSignedInHubEvent = async () => {
try {
Hub.dispatch(
'auth',
{
event: 'signedIn',
data: await getCurrentUser(),
},
'Auth',
AMPLIFY_SYMBOL,
);
} catch (error) {
if ((error as AuthError).name === USER_UNAUTHENTICATED_EXCEPTION) {
throw new AuthError({
name: UNEXPECTED_SIGN_IN_INTERRUPTION_EXCEPTION,
message: ERROR_MESSAGE,
recoverySuggestion:
'This most likely is due to auth tokens not being persisted. If you are using cookie store, please ensure cookies can be correctly set from your server.',
});
}

throw error;
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { cacheCognitoTokens } from '../../tokenProvider/cacheTokens';
import { getCurrentUser } from '../../apis/getCurrentUser';
import { createOAuthError } from './createOAuthError';
import { cognitoUserPoolsTokenProvider } from '../../tokenProvider';
import { dispatchSignedInHubEvent } from '../dispatchSignedInHubEvent';

export const completeOAuthFlow = async ({
currentUrl,
Expand Down Expand Up @@ -250,12 +251,7 @@ const completeFlow = async ({
);
}
Hub.dispatch('auth', { event: 'signInWithRedirect' }, 'Auth', AMPLIFY_SYMBOL);
Hub.dispatch(
'auth',
{ event: 'signedIn', data: await getCurrentUser() },
'Auth',
AMPLIFY_SYMBOL,
);
await dispatchSignedInHubEvent();
clearHistory(redirectUri);
};

Expand Down
4 changes: 2 additions & 2 deletions packages/aws-amplify/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@
"name": "[Auth] confirmSignIn (Cognito)",
"path": "./dist/esm/auth/index.mjs",
"import": "{ confirmSignIn }",
"limit": "25.96 kB"
"limit": "26.40 kB"
},
{
"name": "[Auth] updateMFAPreference (Cognito)",
Expand Down Expand Up @@ -448,7 +448,7 @@
"name": "[Auth] Basic Auth Flow (Cognito)",
"path": "./dist/esm/auth/index.mjs",
"import": "{ signIn, signOut, fetchAuthSession, confirmSignIn }",
"limit": "28.00 kB"
"limit": "28.50 kB"
},
{
"name": "[Auth] OAuth Auth Flow (Cognito)",
Expand Down

0 comments on commit e4ae0f6

Please sign in to comment.