diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 599ff0c1b0e..52ee484d013 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -124,3 +124,4 @@ jobs:
VALID_PASSWORD: ${{ secrets.VALID_PASSWORD }}
VALID_EMAIL_SETUP_MFA: ${{ secrets.VALID_EMAIL_SETUP_MFA }}
VALID_PASSWORD_SETUP_MFA: ${{ secrets.VALID_PASSWORD_SETUP_MFA }}
+ UNVERIFIED_EMAIL: ${{ secrets.UNVERIFIED_EMAIL }}
diff --git a/examples/next/pages/ui/components/authenticator/sign-in-sms-mfa/index.page.tsx b/examples/next/pages/ui/components/authenticator/sign-in-sms-mfa/index.page.tsx
index f90f7ebb8ed..7c4ab18dff2 100644
--- a/examples/next/pages/ui/components/authenticator/sign-in-sms-mfa/index.page.tsx
+++ b/examples/next/pages/ui/components/authenticator/sign-in-sms-mfa/index.page.tsx
@@ -1,5 +1,6 @@
import { Authenticator } from '@aws-amplify/ui-react';
-import { Amplify } from 'aws-amplify';
+import { dict } from '@aws-amplify/ui-core';
+import { Amplify, I18n } from 'aws-amplify';
import awsExports from '@environments/auth-with-phone-and-sms-mfa/src/aws-exports';
@@ -10,6 +11,18 @@ Amplify.configure({
},
});
+I18n.putVocabularies(dict);
+
export default function AuthenticatorWithSmsMfa() {
- return ;
+ return (
+
+ {({ send }) => {
+ return (
+ <>
+
+ >
+ );
+ }}
+
+ );
}
diff --git a/examples/next/pages/ui/components/authenticator/sign-in-totp-mfa/index.page.tsx b/examples/next/pages/ui/components/authenticator/sign-in-totp-mfa/index.page.tsx
index 0a9c371bca3..a3cdbd2d8a0 100644
--- a/examples/next/pages/ui/components/authenticator/sign-in-totp-mfa/index.page.tsx
+++ b/examples/next/pages/ui/components/authenticator/sign-in-totp-mfa/index.page.tsx
@@ -1,5 +1,6 @@
import { Authenticator } from '@aws-amplify/ui-react';
-import { Amplify } from 'aws-amplify';
+import { dict } from '@aws-amplify/ui-core';
+import { Amplify, I18n } from 'aws-amplify';
import awsExports from '@environments/auth-with-totp-mfa/src/aws-exports';
@@ -10,6 +11,8 @@ Amplify.configure({
},
});
+I18n.putVocabularies(dict);
+
export default function SignInTotpMfa() {
return (
diff --git a/examples/next/pages/ui/components/authenticator/sign-in-totp-sms-mfa/index.page.tsx b/examples/next/pages/ui/components/authenticator/sign-in-totp-sms-mfa/index.page.tsx
index e85d7a6347a..642fa75c16c 100644
--- a/examples/next/pages/ui/components/authenticator/sign-in-totp-sms-mfa/index.page.tsx
+++ b/examples/next/pages/ui/components/authenticator/sign-in-totp-sms-mfa/index.page.tsx
@@ -1,5 +1,6 @@
import { Authenticator } from 'aws-amplify-react';
-import { Amplify } from 'aws-amplify';
+import { dict } from '@aws-amplify/ui-core';
+import { Amplify, I18n } from 'aws-amplify';
import awsExports from '@environments/auth-with-totp-and-sms-mfa/src/aws-exports';
@@ -10,6 +11,8 @@ Amplify.configure({
},
});
+I18n.putVocabularies(dict);
+
export default function SignInTotpSmsMfa() {
return ;
}
diff --git a/examples/next/pages/ui/components/authenticator/sign-in-with-email/index.page.tsx b/examples/next/pages/ui/components/authenticator/sign-in-with-email/index.page.tsx
index 172b92044d6..760c0853ea5 100644
--- a/examples/next/pages/ui/components/authenticator/sign-in-with-email/index.page.tsx
+++ b/examples/next/pages/ui/components/authenticator/sign-in-with-email/index.page.tsx
@@ -1,5 +1,6 @@
import { Authenticator } from '@aws-amplify/ui-react';
-import { Amplify } from 'aws-amplify';
+import { dict } from '@aws-amplify/ui-core';
+import { Amplify, I18n } from 'aws-amplify';
import awsExports from '@environments/auth-with-email/src/aws-exports';
Amplify.configure({
@@ -9,6 +10,8 @@ Amplify.configure({
},
});
+I18n.putVocabularies(dict);
+
export default function AuthenticatorWithEmail() {
return (
<>
diff --git a/examples/next/pages/ui/components/authenticator/sign-in-with-phone/index.page.tsx b/examples/next/pages/ui/components/authenticator/sign-in-with-phone/index.page.tsx
index 6b2905aca2e..010e6cf35a4 100644
--- a/examples/next/pages/ui/components/authenticator/sign-in-with-phone/index.page.tsx
+++ b/examples/next/pages/ui/components/authenticator/sign-in-with-phone/index.page.tsx
@@ -1,5 +1,6 @@
import { Authenticator } from '@aws-amplify/ui-react';
-import { Amplify } from 'aws-amplify';
+import { dict } from '@aws-amplify/ui-core';
+import { Amplify, I18n } from 'aws-amplify';
import awsExports from '@environments/auth-with-phone-number/src/aws-exports';
Amplify.configure({
@@ -9,6 +10,8 @@ Amplify.configure({
},
});
+I18n.putVocabularies(dict);
+
export default function AuthenticatorWithPhoneNumber() {
return (
<>
diff --git a/examples/next/pages/ui/components/authenticator/sign-in-with-username/index.page.tsx b/examples/next/pages/ui/components/authenticator/sign-in-with-username/index.page.tsx
index 5b89ff4e790..2b1d1fd3971 100644
--- a/examples/next/pages/ui/components/authenticator/sign-in-with-username/index.page.tsx
+++ b/examples/next/pages/ui/components/authenticator/sign-in-with-username/index.page.tsx
@@ -1,5 +1,6 @@
import { Authenticator } from '@aws-amplify/ui-react';
-import { Amplify } from 'aws-amplify';
+import { dict } from '@aws-amplify/ui-core';
+import { Amplify, I18n } from 'aws-amplify';
import awsExports from '@environments/auth-with-username-no-attributes/src/aws-exports';
@@ -10,6 +11,8 @@ Amplify.configure({
},
});
+I18n.putVocabularies(dict);
+
export default function AuthenticatorWithUsername() {
return (
diff --git a/examples/next/pages/ui/components/authenticator/sign-up-with-email/index.page.tsx b/examples/next/pages/ui/components/authenticator/sign-up-with-email/index.page.tsx
index 0ddca339bd8..d466dc76cc8 100644
--- a/examples/next/pages/ui/components/authenticator/sign-up-with-email/index.page.tsx
+++ b/examples/next/pages/ui/components/authenticator/sign-up-with-email/index.page.tsx
@@ -1,5 +1,6 @@
import { Authenticator } from '@aws-amplify/ui-react';
-import { Amplify } from 'aws-amplify';
+import { dict } from '@aws-amplify/ui-core';
+import { Amplify, I18n } from 'aws-amplify';
import awsExports from '@environments/auth-with-email/src/aws-exports';
Amplify.configure({
@@ -9,6 +10,8 @@ Amplify.configure({
},
});
+I18n.putVocabularies(dict);
+
export default function AuthenticatorWithEmail() {
return ;
}
diff --git a/examples/next/pages/ui/components/authenticator/sign-up-with-phone/index.page.tsx b/examples/next/pages/ui/components/authenticator/sign-up-with-phone/index.page.tsx
index 67807ecf33a..f4da9f08938 100644
--- a/examples/next/pages/ui/components/authenticator/sign-up-with-phone/index.page.tsx
+++ b/examples/next/pages/ui/components/authenticator/sign-up-with-phone/index.page.tsx
@@ -1,5 +1,6 @@
import { Authenticator } from '@aws-amplify/ui-react';
-import { Amplify } from 'aws-amplify';
+import { dict } from '@aws-amplify/ui-core';
+import { Amplify, I18n } from 'aws-amplify';
import awsExports from '@environments/auth-with-phone-number/src/aws-exports';
Amplify.configure({
@@ -9,6 +10,8 @@ Amplify.configure({
},
});
+I18n.putVocabularies(dict);
+
export default function AuthenticatorWithPhone() {
return (
<>
diff --git a/examples/next/pages/ui/components/authenticator/sign-up/index.page.tsx b/examples/next/pages/ui/components/authenticator/sign-up/index.page.tsx
index 2276d14ef40..75c46f59b8a 100644
--- a/examples/next/pages/ui/components/authenticator/sign-up/index.page.tsx
+++ b/examples/next/pages/ui/components/authenticator/sign-up/index.page.tsx
@@ -1,10 +1,13 @@
import { Authenticator } from '@aws-amplify/ui-react';
-import { Amplify } from 'aws-amplify';
+import { dict } from '@aws-amplify/ui-core';
+import { Amplify, I18n } from 'aws-amplify';
import awsExports from '@environments/auth-with-username-no-attributes/src/aws-exports';
Amplify.configure(awsExports);
+I18n.putVocabularies(dict);
+
export default function AuthenticatorWithUsername() {
return ;
}
diff --git a/examples/next/pages/ui/components/authenticator/withAuthenticator/index.page.tsx b/examples/next/pages/ui/components/authenticator/withAuthenticator/index.page.tsx
index c792a240600..c8dbdaa4bc6 100644
--- a/examples/next/pages/ui/components/authenticator/withAuthenticator/index.page.tsx
+++ b/examples/next/pages/ui/components/authenticator/withAuthenticator/index.page.tsx
@@ -1,9 +1,12 @@
import { withAuthenticator } from '@aws-amplify/ui-react';
-import { Amplify } from 'aws-amplify';
+import { dict } from '@aws-amplify/ui-core';
+import { Amplify, I18n } from 'aws-amplify';
import awsExports from '@environments/auth-with-username-no-attributes/src/aws-exports';
Amplify.configure(awsExports);
+I18n.putVocabularies(dict);
+
function App({ state, send }) {
return (
<>
diff --git a/packages/core/src/machines/actors/auth/signIn.ts b/packages/core/src/machines/actors/auth/signIn.ts
index d8767419ffe..7fae59c6404 100644
--- a/packages/core/src/machines/actors/auth/signIn.ts
+++ b/packages/core/src/machines/actors/auth/signIn.ts
@@ -58,7 +58,7 @@ export const signInActor = createMachine(
},
{
actions: 'setUser',
- target: 'resolved',
+ target: 'verifying',
},
],
onError: [
@@ -74,6 +74,25 @@ export const signInActor = createMachine(
],
},
},
+ verifying: {
+ entry: ['clearError', sendUpdate()],
+ invoke: {
+ src: 'checkVerifiedContact',
+ onDone: [
+ {
+ cond: 'shouldRequestVerification',
+ target: '#signInActor.verifyUser',
+ },
+ {
+ target: 'resolved',
+ },
+ ],
+ onError: {
+ actions: 'setRemoteError',
+ target: 'edit',
+ },
+ },
+ },
resolved: { always: '#signInActor.resolved' },
rejected: { always: '#signInActor.rejected' },
},
@@ -162,6 +181,65 @@ export const signInActor = createMachine(
},
},
},
+ verifyUser: {
+ initial: 'edit',
+ exit: ['clearFormValues', 'clearError'],
+ states: {
+ edit: {
+ entry: sendUpdate(),
+ on: {
+ SUBMIT: 'submit',
+ SKIP: '#signInActor.resolved',
+ CHANGE: { actions: 'handleInput' },
+ },
+ },
+ submit: {
+ entry: 'clearError',
+ invoke: {
+ src: 'verifyUser',
+ onDone: {
+ target: '#signInActor.confirmVerifyUser',
+ },
+ onError: {
+ actions: 'setRemoteError',
+ target: 'edit',
+ },
+ },
+ },
+ },
+ },
+ confirmVerifyUser: {
+ initial: 'edit',
+ exit: [
+ 'clearFormValues',
+ 'clearError',
+ 'clearUnverifiedAttributes',
+ 'clearAttributeToVerify',
+ ],
+ states: {
+ edit: {
+ entry: sendUpdate(),
+ on: {
+ SUBMIT: 'submit',
+ SKIP: '#signInActor.resolved',
+ CHANGE: { actions: 'handleInput' },
+ },
+ },
+ submit: {
+ entry: 'clearError',
+ invoke: {
+ src: 'confirmVerifyUser',
+ onDone: {
+ target: '#signInActor.resolved',
+ },
+ onError: {
+ actions: 'setRemoteError',
+ target: 'edit',
+ },
+ },
+ },
+ },
+ },
resolved: {
type: 'final',
data: (context) => ({
@@ -202,6 +280,8 @@ export const signInActor = createMachine(
clearChallengeName: assign({ challengeName: undefined }),
clearError: assign({ remoteError: '' }),
clearFormValues: assign({ formValues: {} }),
+ clearUnverifiedAttributes: assign({ unverifiedAttributes: undefined }),
+ clearAttributeToVerify: assign({ attributeToVerify: undefined }),
},
guards: {
shouldConfirmSignIn: (_, event): boolean => {
@@ -229,6 +309,17 @@ export const signInActor = createMachine(
shouldAutoSignIn: (context) => {
return !!(context.intent && context.intent === 'autoSignIn');
},
+ shouldRequestVerification: (context, event): boolean => {
+ const { unverified } = event.data;
+
+ if (Object.keys(unverified).length > 0) {
+ context.unverifiedAttributes = unverified;
+
+ return true;
+ }
+
+ return false;
+ },
},
services: {
async signIn(context) {
@@ -268,6 +359,32 @@ export const signInActor = createMachine(
const { provider } = event.data;
const result = await Auth.federatedSignIn({ provider });
+ return result;
+ },
+ async checkVerifiedContact(context, event) {
+ const { user } = context;
+ const result = await Auth.verifiedContact(user);
+
+ return result;
+ },
+ async verifyUser(context, event) {
+ const result = await Auth.verifyCurrentUserAttribute(
+ event.data.unverifiedAttr
+ );
+
+ context.attributeToVerify = event.data.unverifiedAttr;
+
+ return result;
+ },
+ async confirmVerifyUser(context, event) {
+ const { attributeToVerify } = context;
+ const { confirmation_code: code } = event.data;
+
+ const result = await Auth.verifyCurrentUserAttributeSubmit(
+ attributeToVerify,
+ code
+ );
+
return result;
},
},
diff --git a/packages/core/src/machines/authMachine.ts b/packages/core/src/machines/authMachine.ts
index 701019f5ec6..a301839d970 100644
--- a/packages/core/src/machines/authMachine.ts
+++ b/packages/core/src/machines/authMachine.ts
@@ -92,6 +92,7 @@ export const authMachine = createMachine(
RESEND: { actions: 'forwardToActor' },
SIGN_OUT: { actions: 'forwardToActor' },
SIGN_IN: { actions: 'forwardToActor' },
+ SKIP: { actions: 'forwardToActor' },
},
},
{
diff --git a/packages/core/src/types/authMachine.ts b/packages/core/src/types/authMachine.ts
index bd46faf06e7..a224b556fcc 100644
--- a/packages/core/src/types/authMachine.ts
+++ b/packages/core/src/types/authMachine.ts
@@ -20,6 +20,8 @@ export interface SignInContext {
challengeName?: string;
authAttributes?: Record;
intent?: string;
+ unverifiedAttributes?: Record;
+ attributeToVerify?: string;
}
export interface SignUpContext {
@@ -73,6 +75,7 @@ export type AuthEventTypes =
| 'CHANGE'
| 'FEDERATED_SIGN_IN'
| 'RESET_PASSWORD'
+ | 'SKIP'
| InvokeActorEventTypes;
export enum AuthChallengeNames {
diff --git a/packages/e2e/.env.example b/packages/e2e/.env.example
index 46020a75320..a2537c9cd3a 100644
--- a/packages/e2e/.env.example
+++ b/packages/e2e/.env.example
@@ -4,6 +4,7 @@ INVALID_EMAIL=
UNCONFIRMED_EMAIL=
UNKNOWN_EMAIL=
VALID_EMAIL=
+UNVERIFIED_EMAIL=
CONFIRMED_PHONE_NUMBER=
FORCE_CHANGE_PHONE_NUMBER=
diff --git a/packages/e2e/cypress/integration/ui/components/authenticator/verify-user.feature b/packages/e2e/cypress/integration/ui/components/authenticator/verify-user.feature
new file mode 100644
index 00000000000..dc67c7c1e4a
--- /dev/null
+++ b/packages/e2e/cypress/integration/ui/components/authenticator/verify-user.feature
@@ -0,0 +1,18 @@
+Feature: Verify User
+
+ Amplify's SignIn component uses AWS Cognito's authentication
+ service to provide a sign in experience to your application's
+ users.
+
+ Background:
+ Given I'm running the example "ui/components/authenticator/sign-in-federated"
+
+ @next @react
+ Scenario: Verify User with valid but unverified email
+ When I type a valid but unverified email "UNVERIFIED_EMAIL"
+ And I type a valid password "VALID_PASSWORD"
+ And I click the "Sign in" button
+ Then I will be redirected to the verify user page
+ And I click on the first radio button
+ And I click the "Verify" button
+ Then I will be redirected to the confirm verify user page
diff --git a/packages/e2e/cypress/integration/ui/components/authenticator/verify-user/verify-user.steps.ts b/packages/e2e/cypress/integration/ui/components/authenticator/verify-user/verify-user.steps.ts
new file mode 100644
index 00000000000..8427db674ae
--- /dev/null
+++ b/packages/e2e/cypress/integration/ui/components/authenticator/verify-user/verify-user.steps.ts
@@ -0,0 +1,38 @@
+import { And, Given, Then, When } from 'cypress-cucumber-preprocessor/steps';
+
+Given("I'm running the example {string}", (url: string) => {
+ cy.visit(url);
+});
+
+When('I click on the {string} button', (name: string) => {
+ cy.findByRole('button', { name }).click();
+});
+
+And('I type a valid but unverified email {string}', (email: string) => {
+ cy.findByRole('textbox', { name: /email/i }).type(Cypress.env(email));
+});
+
+And('I type a valid password {string}', (password: string) => {
+ cy.findByLabelText(/password/i).type(Cypress.env(password));
+});
+
+And('I click the {string} button', (name: string) => {
+ cy.findByRole('button', { name }).click();
+});
+
+And('I click on the first radio button', () => {
+ cy.findByRole('radio').click();
+});
+
+Then('I will be redirected to the verify user page', () => {
+ cy.findByRole('radio').should('exist');
+});
+
+Then('I will be redirected to the confirm verify user page', () => {
+ cy.findByRole('document').contains(new RegExp('Code *', 'i'));
+});
+
+Then('I see {string}', (message: string) => {
+ const [messageString, username] = message.split(' ');
+ cy.get('body').contains([messageString, Cypress.env(username)].join(' '));
+});
diff --git a/packages/react/src/components/Authenticator/ResetPassword/ConfirmResetPassword.tsx b/packages/react/src/components/Authenticator/ResetPassword/ConfirmResetPassword.tsx
index 7fa19dd6bb2..5347990d6ca 100644
--- a/packages/react/src/components/Authenticator/ResetPassword/ConfirmResetPassword.tsx
+++ b/packages/react/src/components/Authenticator/ResetPassword/ConfirmResetPassword.tsx
@@ -4,7 +4,7 @@ import {
ConfirmationCodeInput,
ErrorText,
PasswordInput,
- SignInOrSubmitFooter,
+ TwoButtonSubmitFooter,
} from '../shared';
export const ConfirmResetPassword = (): JSX.Element => {
@@ -74,7 +74,12 @@ export const ConfirmResetPassword = (): JSX.Element => {
-
+
);
};
diff --git a/packages/react/src/components/Authenticator/ResetPassword/ResetPassword.tsx b/packages/react/src/components/Authenticator/ResetPassword/ResetPassword.tsx
index 30cd16c4b8f..7bdbaae4ec2 100644
--- a/packages/react/src/components/Authenticator/ResetPassword/ResetPassword.tsx
+++ b/packages/react/src/components/Authenticator/ResetPassword/ResetPassword.tsx
@@ -1,6 +1,6 @@
import { getActorState, ResetPasswordState } from '@aws-amplify/ui-core';
import { useAmplify, useAuth } from '../../../hooks';
-import { ErrorText, SignInOrSubmitFooter } from '../shared';
+import { ErrorText, TwoButtonSubmitFooter } from '../shared';
export const ResetPassword = (): JSX.Element => {
const amplifyNamespace = 'Authenticator.ResetPassword';
@@ -56,8 +56,11 @@ export const ResetPassword = (): JSX.Element => {
-
diff --git a/packages/react/src/components/Authenticator/VerifyUser/ConfirmVerifyUser.tsx b/packages/react/src/components/Authenticator/VerifyUser/ConfirmVerifyUser.tsx
new file mode 100644
index 00000000000..67245921dcf
--- /dev/null
+++ b/packages/react/src/components/Authenticator/VerifyUser/ConfirmVerifyUser.tsx
@@ -0,0 +1,57 @@
+import { getActorState, SignInState } from '@aws-amplify/ui-core';
+import { I18n } from '@aws-amplify/core';
+
+import { useAmplify, useAuth } from '../../../hooks';
+import {
+ ConfirmationCodeInput,
+ ErrorText,
+ TwoButtonSubmitFooter,
+} from '../shared';
+
+export const ConfirmVerifyUser = (): JSX.Element => {
+ const amplifyNamespace = 'Authenticator.ConfirmVerifyUser';
+ const {
+ components: { Fieldset, Form, Heading },
+ } = useAmplify(amplifyNamespace);
+
+ const [_state, send] = useAuth();
+ const actorState: SignInState = getActorState(_state);
+ const isPending = actorState.matches('confirmVerifyUser.pending');
+
+ const headerText = I18n.get(
+ 'Account recovery requires verified contact information'
+ );
+
+ return (
+
+ );
+};
diff --git a/packages/react/src/components/Authenticator/VerifyUser/VerifyUser.tsx b/packages/react/src/components/Authenticator/VerifyUser/VerifyUser.tsx
new file mode 100644
index 00000000000..6c3872e74b3
--- /dev/null
+++ b/packages/react/src/components/Authenticator/VerifyUser/VerifyUser.tsx
@@ -0,0 +1,89 @@
+import {
+ getActorState,
+ getActorContext,
+ SignInState,
+ SignInContext,
+ authInputAttributes,
+} from '@aws-amplify/ui-core';
+import { I18n } from '@aws-amplify/core';
+
+import { useAmplify, useAuth } from '../../../hooks';
+import { ErrorText, TwoButtonSubmitFooter } from '../shared';
+
+const generateRadioGroup = (
+ attributes: Record
+): JSX.Element[] => {
+ const radioButtons: JSX.Element[] = [];
+
+ for (const [key, value] of Object.entries(attributes)) {
+ const radio = (
+
+ );
+
+ radioButtons.push(radio);
+ }
+
+ return radioButtons;
+};
+
+export const VerifyUser = (): JSX.Element => {
+ const amplifyNamespace = 'Authenticator.VerifyUser';
+ const {
+ components: { Fieldset, Form, Heading },
+ } = useAmplify(amplifyNamespace);
+
+ const [_state, send] = useAuth();
+ const actorState: SignInState = getActorState(_state);
+ const context = getActorContext(_state) as SignInContext;
+ const isPending = actorState.matches('verifyUser.pending');
+
+ const headerText = I18n.get(
+ 'Account recovery requires verified contact information'
+ );
+ const footerSubmitText = isPending ? (
+ <>Verifying…>
+ ) : (
+ <>{I18n.get('Verify')}>
+ );
+
+ const verificationRadioGroup = (
+
+ );
+
+ return (
+
+ );
+};
diff --git a/packages/react/src/components/Authenticator/VerifyUser/index.ts b/packages/react/src/components/Authenticator/VerifyUser/index.ts
new file mode 100644
index 00000000000..89a7dbbe4d7
--- /dev/null
+++ b/packages/react/src/components/Authenticator/VerifyUser/index.ts
@@ -0,0 +1,2 @@
+export * from './ConfirmVerifyUser';
+export * from './VerifyUser';
diff --git a/packages/react/src/components/Authenticator/index.tsx b/packages/react/src/components/Authenticator/index.tsx
index 8281faa4c07..b0a857219dd 100644
--- a/packages/react/src/components/Authenticator/index.tsx
+++ b/packages/react/src/components/Authenticator/index.tsx
@@ -10,6 +10,7 @@ import { ConfirmResetPassword, ResetPassword } from './ResetPassword';
import { SetupTOTP } from './SetupTOTP';
import { SignIn } from './SignIn';
import { SignUp } from './SignUp';
+import { ConfirmVerifyUser, VerifyUser } from './VerifyUser';
export function Authenticator({
className = null,
@@ -61,6 +62,10 @@ export function Authenticator({
return ;
case actorState?.matches('confirmResetPassword'):
return ;
+ case actorState?.matches('verifyUser'):
+ return ;
+ case actorState?.matches('confirmVerifyUser'):
+ return ;
default:
console.warn('Unhandled Auth state', state.value);
return null;
diff --git a/packages/react/src/components/Authenticator/shared/SignInOrSubmitFooter.tsx b/packages/react/src/components/Authenticator/shared/TwoButtonSubmitFooter.tsx
similarity index 52%
rename from packages/react/src/components/Authenticator/shared/SignInOrSubmitFooter.tsx
rename to packages/react/src/components/Authenticator/shared/TwoButtonSubmitFooter.tsx
index 454078e7060..9fc76321f41 100644
--- a/packages/react/src/components/Authenticator/shared/SignInOrSubmitFooter.tsx
+++ b/packages/react/src/components/Authenticator/shared/TwoButtonSubmitFooter.tsx
@@ -1,29 +1,42 @@
+import { AuthEventTypes } from '@aws-amplify/ui-core';
+
import { useAmplify, useAuth } from '../../../hooks';
-export interface SignInOrSubmitFooterProps {
+export interface TwoButtonSubmitFooterProps {
amplifyNamespace: string;
+ isPending: boolean;
+ cancelButtonSendType: AuthEventTypes;
+ cancelButtonText: string;
submitButtonText?: JSX.Element;
}
-export const SignInOrSubmitFooter = (
- props: SignInOrSubmitFooterProps
+export const TwoButtonSubmitFooter = (
+ props: TwoButtonSubmitFooterProps
): JSX.Element => {
- const { amplifyNamespace, submitButtonText } = props;
+ const {
+ amplifyNamespace,
+ cancelButtonSendType,
+ cancelButtonText,
+ isPending,
+ submitButtonText,
+ } = props;
const {
components: { Button, Footer, Spacer },
} = useAmplify(amplifyNamespace);
const [state, send] = useAuth();
- const isPending = state.matches('resetPassword.pending');
const defaultSubmitText = isPending ? <>Submitting…> : <>Submit>;
const submitText = submitButtonText || defaultSubmitText;
return (