-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(auth): add auto sign-in support (#12229)
* feat: add autoSignIn support * chore: add default verification signUp method * feat(auth): add auto sign-in (#12153) * feat: add autoSignIn support * chore: add default verification signUp method * autoSignIn refactor * chore: remove unused code * feat: add sign-up helpers for auto-sign-in * feat: add auto sign-in helpers * fix build * chore: fix error during auto-sign-in with code * remove unused types * chore: address feedback * fix autoSignIn enable * chore: add unit tests * fix unit tests * chore: remove unsued type * chore: address feedback * chore: address feedback * chore: import hub-internal from core * fix: bundle size * fix bundle size
- Loading branch information
Showing
19 changed files
with
604 additions
and
83 deletions.
There are no files selected for viewing
87 changes: 87 additions & 0 deletions
87
packages/auth/__tests__/providers/cognito/autoSignIn.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import { | ||
CognitoUserPoolsTokenProvider, | ||
signUp, | ||
} from '../../../src/providers/cognito'; | ||
import { autoSignIn } from '../../../src/providers/cognito/apis/autoSignIn'; | ||
import * as signUpClient from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider'; | ||
import { authAPITestParams } from './testUtils/authApiTestParams'; | ||
import { RespondToAuthChallengeCommandOutput } from '../../../src/providers/cognito/utils/clients/CognitoIdentityProvider/types'; | ||
import { Amplify } from 'aws-amplify'; | ||
import * as initiateAuthHelpers from '../../../src/providers/cognito/utils/signInHelpers'; | ||
import { AuthError } from '../../../src/errors/AuthError'; | ||
jest.mock('@aws-amplify/core/lib/clients/handlers/fetch'); | ||
|
||
const authConfig = { | ||
Cognito: { | ||
userPoolClientId: '111111-aaaaa-42d8-891d-ee81a1549398', | ||
userPoolId: 'us-west-2_zzzzz', | ||
}, | ||
}; | ||
CognitoUserPoolsTokenProvider.setAuthConfig(authConfig); | ||
Amplify.configure({ | ||
Auth: authConfig, | ||
}); | ||
describe('Auto sign-in API Happy Path Cases:', () => { | ||
let signUpSpy; | ||
let handleUserSRPAuthflowSpy; | ||
const { user1 } = authAPITestParams; | ||
beforeEach(async () => { | ||
signUpSpy = jest | ||
.spyOn(signUpClient, 'signUp') | ||
.mockImplementationOnce(async () => { | ||
return { | ||
UserConfirmed: true, | ||
}; | ||
}); | ||
|
||
handleUserSRPAuthflowSpy = jest | ||
.spyOn(initiateAuthHelpers, 'handleUserSRPAuthFlow') | ||
.mockImplementationOnce( | ||
async (): Promise<RespondToAuthChallengeCommandOutput> => | ||
authAPITestParams.RespondToAuthChallengeCommandOutput | ||
); | ||
}); | ||
afterEach(() => { | ||
signUpSpy.mockClear(); | ||
handleUserSRPAuthflowSpy.mockClear(); | ||
}); | ||
test('signUp should enable autoSignIn and return COMPLETE_AUTO_SIGN_IN step', async () => { | ||
const resp = await signUp({ | ||
username: user1.username, | ||
password: user1.password, | ||
options: { | ||
userAttributes: { email: user1.email }, | ||
serviceOptions: { | ||
autoSignIn: true, | ||
}, | ||
}, | ||
}); | ||
expect(resp).toEqual({ | ||
isSignUpComplete: true, | ||
nextStep: { | ||
signUpStep: 'COMPLETE_AUTO_SIGN_IN', | ||
}, | ||
}); | ||
expect(signUpSpy).toBeCalledTimes(1); | ||
}); | ||
|
||
test('Auto sign-in should resolve to a signIn output', async () => { | ||
const signInOutput = await autoSignIn(); | ||
expect(signInOutput).toEqual(authAPITestParams.signInResult()); | ||
expect(handleUserSRPAuthflowSpy).toBeCalledTimes(1); | ||
}); | ||
}); | ||
|
||
describe('Auto sign-in API Error Path Cases:', () => { | ||
test('autoSignIn should throw an error when autoSignIn is not enabled', async () => { | ||
try { | ||
await autoSignIn(); | ||
} catch (error) { | ||
expect(error).toBeInstanceOf(AuthError); | ||
expect(error.name).toBe('AutoSignInException'); | ||
} | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import { AuthError } from '../../../errors/AuthError'; | ||
import { AUTO_SIGN_IN_EXCEPTION } from '../../../errors/constants'; | ||
import { AutoSignInCallback } from '../../../types/models'; | ||
import { SignInOutput } from '../types'; | ||
|
||
const initialAutoSignIn: AutoSignInCallback = | ||
async (): Promise<SignInOutput> => { | ||
throw new AuthError({ | ||
name: AUTO_SIGN_IN_EXCEPTION, | ||
message: | ||
'The autoSignIn flow has not started, or has been cancelled/completed.', | ||
recoverySuggestion: | ||
'Please try to use the signIn API or log out before starting a new autoSignIn flow.', | ||
}); | ||
}; | ||
|
||
/** | ||
* Signs a user in automatically after finishing the sign-up process. | ||
* | ||
* This API will automatically sign a user in if the autoSignIn flow has been completed in the following cases: | ||
* - User confirmed their account with a verification code sent to their phone or email (default option). | ||
* - User confirmed their account with a verification link sent to their phone or email. In order to | ||
* enable this option you need to go to the Amazon Cognito [console](https://aws.amazon.com/pm/cognito), | ||
* look for your userpool, then go to the `Messaging` tab and enable `link` mode inside the `Verification message` option. | ||
* Finally you need to define the `signUpVerificationMethod` in your `Auth` config. | ||
* | ||
* @example | ||
* ```typescript | ||
* Amplify.configure({ | ||
* Auth: { | ||
* Cognito: { | ||
* ...cognitoConfig, | ||
* signUpVerificationMethod: "link" // the default value is "code" | ||
* } | ||
* }}); | ||
* ``` | ||
* | ||
* @throws AutoSignInException - Thrown when the autoSignIn flow has not started, or has been cancelled/completed. | ||
* @returns The signInOutput. | ||
* | ||
* @example | ||
* ```typescript | ||
* // handleSignUp.ts | ||
* async function handleSignUp( | ||
* username:string, | ||
* password:string | ||
* ){ | ||
* try { | ||
* const { nextStep } = await signUp({ | ||
* username, | ||
* password, | ||
* options: { | ||
* userAttributes:{ email:'email@email.com'}, | ||
* serviceOptions: { | ||
* autoSignIn: true // This enables the auto sign-in flow. | ||
* }, | ||
* }, | ||
* }); | ||
* | ||
* handleSignUpStep(nextStep); | ||
* | ||
* } catch (error) { | ||
* console.log(error); | ||
* } | ||
* } | ||
* | ||
* // handleConfirmSignUp.ts | ||
* async function handleConfirmSignUp(username:string, confirmationCode:string) { | ||
* try { | ||
* const { nextStep } = await confirmSignUp({ | ||
* username, | ||
* confirmationCode, | ||
* }); | ||
* | ||
* handleSignUpStep(nextStep); | ||
* } catch (error) { | ||
* console.log(error); | ||
* } | ||
* } | ||
* | ||
* // signUpUtils.ts | ||
* async function handleSignUpStep( step: SignUpOutput["nextStep"]) { | ||
* switch (step.signUpStep) { | ||
* case "CONFIRM_SIGN_UP": | ||
* | ||
* // Redirect end-user to confirm-sign up screen. | ||
* | ||
* case "COMPLETE_AUTO_SIGN_IN": | ||
* const codeDeliveryDetails = step.codeDeliveryDetails; | ||
* if (codeDeliveryDetails) { | ||
* // Redirect user to confirm-sign-up with link screen. | ||
* } | ||
* const signInOutput = await autoSignIn(); | ||
* // handle sign-in steps | ||
* } | ||
* | ||
* ``` | ||
*/ | ||
export let autoSignIn: AutoSignInCallback = initialAutoSignIn; | ||
|
||
/** | ||
* Sets the context of autoSignIn at run time. | ||
* @internal | ||
*/ | ||
export function setAutoSignIn(callback: AutoSignInCallback) { | ||
autoSignIn = callback; | ||
} | ||
|
||
/** | ||
* Resets the context | ||
* | ||
* @internal | ||
*/ | ||
export function resetAutoSignIn() { | ||
autoSignIn = initialAutoSignIn; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.