Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -10,6 +11,18 @@ Amplify.configure({
},
});

I18n.putVocabularies(dict);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the aws-amplify-react package, we do this call ourselves when exporting the modules: https://github.com/aws-amplify/amplify-js/blob/main/packages/aws-amplify-react/src/index.tsx#L30

Is this something we expect customers to do in their applications?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now, yes. Because this might look different in React vs Angular vs Vue. Suggestion proposed by Eric on my last PR - #189 (comment)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


export default function AuthenticatorWithSmsMfa() {
return <Authenticator />;
return (
<Authenticator>
{({ send }) => {
return (
<>
<button onClick={() => send('SIGN_OUT')}>Sign out</button>
</>
);
}}
</Authenticator>
);
}
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -10,6 +11,8 @@ Amplify.configure({
},
});

I18n.putVocabularies(dict);

export default function SignInTotpMfa() {
return (
<Authenticator>
Expand Down
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -10,6 +11,8 @@ Amplify.configure({
},
});

I18n.putVocabularies(dict);

export default function SignInTotpSmsMfa() {
return <Authenticator />;
}
Original file line number Diff line number Diff line change
@@ -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({
Expand All @@ -9,6 +10,8 @@ Amplify.configure({
},
});

I18n.putVocabularies(dict);

export default function AuthenticatorWithEmail() {
return (
<>
Expand Down
Original file line number Diff line number Diff line change
@@ -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({
Expand All @@ -9,6 +10,8 @@ Amplify.configure({
},
});

I18n.putVocabularies(dict);

export default function AuthenticatorWithPhoneNumber() {
return (
<>
Expand Down
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -10,6 +11,8 @@ Amplify.configure({
},
});

I18n.putVocabularies(dict);

export default function AuthenticatorWithUsername() {
return (
<Authenticator>
Expand Down
Original file line number Diff line number Diff line change
@@ -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({
Expand All @@ -9,6 +10,8 @@ Amplify.configure({
},
});

I18n.putVocabularies(dict);

export default function AuthenticatorWithEmail() {
return <Authenticator />;
}
Original file line number Diff line number Diff line change
@@ -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({
Expand All @@ -9,6 +10,8 @@ Amplify.configure({
},
});

I18n.putVocabularies(dict);

export default function AuthenticatorWithPhone() {
return (
<>
Expand Down
Original file line number Diff line number Diff line change
@@ -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 <Authenticator />;
}
Original file line number Diff line number Diff line change
@@ -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 (
<>
Expand Down
119 changes: 118 additions & 1 deletion packages/core/src/machines/actors/auth/signIn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export const signInActor = createMachine<SignInContext, AuthEvent>(
},
{
actions: 'setUser',
target: 'resolved',
target: 'verifying',
},
],
onError: [
Expand All @@ -74,6 +74,25 @@ export const signInActor = createMachine<SignInContext, AuthEvent>(
],
},
},
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' },
},
Expand Down Expand Up @@ -162,6 +181,65 @@ export const signInActor = createMachine<SignInContext, AuthEvent>(
},
},
},
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) => ({
Expand Down Expand Up @@ -202,6 +280,8 @@ export const signInActor = createMachine<SignInContext, AuthEvent>(
clearChallengeName: assign({ challengeName: undefined }),
clearError: assign({ remoteError: '' }),
clearFormValues: assign({ formValues: {} }),
clearUnverifiedAttributes: assign({ unverifiedAttributes: undefined }),
clearAttributeToVerify: assign({ attributeToVerify: undefined }),
},
guards: {
shouldConfirmSignIn: (_, event): boolean => {
Expand Down Expand Up @@ -229,6 +309,17 @@ export const signInActor = createMachine<SignInContext, AuthEvent>(
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) {
Expand Down Expand Up @@ -268,6 +359,32 @@ export const signInActor = createMachine<SignInContext, AuthEvent>(
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;
},
},
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/machines/authMachine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export const authMachine = createMachine<AuthContext, AuthEvent>(
RESEND: { actions: 'forwardToActor' },
SIGN_OUT: { actions: 'forwardToActor' },
SIGN_IN: { actions: 'forwardToActor' },
SKIP: { actions: 'forwardToActor' },
},
},
{
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/types/authMachine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ export interface SignInContext {
challengeName?: string;
authAttributes?: Record<string, any>;
intent?: string;
unverifiedAttributes?: Record<string, string>;
attributeToVerify?: string;
}

export interface SignUpContext {
Expand Down Expand Up @@ -73,6 +75,7 @@ export type AuthEventTypes =
| 'CHANGE'
| 'FEDERATED_SIGN_IN'
| 'RESET_PASSWORD'
| 'SKIP'
| InvokeActorEventTypes;

export enum AuthChallengeNames {
Expand Down
1 change: 1 addition & 0 deletions packages/e2e/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ INVALID_EMAIL=
UNCONFIRMED_EMAIL=
UNKNOWN_EMAIL=
VALID_EMAIL=
UNVERIFIED_EMAIL=

CONFIRMED_PHONE_NUMBER=
FORCE_CHANGE_PHONE_NUMBER=
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Loading