Amplify UI

Customization

Override and customize your Authenticator.

Headers & Footers

The Authenticator has several "slots" that you can customize to add messaging & functionality to meet your app's needs.

The following example customizes these slots with:

  • Custom header above the Authenticator with the Amplify logo
  • Custom footer below the Authenticator with © All Rights Reserved
  • Custom Sign In header with Sign in to your account
  • Custom Sign In footer with a Reset Password link
  • Custom Sign Up header with Create a new account
  • Custom Sign Up footer with a Back to Sign In link
  • Custom Confirm Sign Up header with an Enter Information header
  • Custom Confirm Sign Up footer with a Footer Information message
const components = {
Header() {
const { tokens } = useTheme(); return ( <View textAlign="center" padding={tokens.space.large}> <Image alt="Amplify logo" src="https://docs.amplify.aws/assets/logo-dark.svg" /> </View> ); },
Footer() {
const { tokens } = useTheme(); return ( <View textAlign="center" padding={tokens.space.large}> <Text color={tokens.colors.neutral[80]}> &copy; All Rights Reserved </Text> </View> ); },
SignIn: {
Header() {
const { tokens } = useTheme(); return ( <Heading padding={`${tokens.space.xl} 0 0 ${tokens.space.xl}`} level={3} > Sign in to your account </Heading> ); },
Footer() {
const { toForgotPassword } = useAuthenticator(); return ( <View textAlign="center"> <Button fontWeight="normal" onClick={toForgotPassword} size="small" variation="link" > Reset Password </Button> </View> ); }, },
SignUp: {
Header() {
const { tokens } = useTheme(); return ( <Heading padding={`${tokens.space.xl} 0 0 ${tokens.space.xl}`} level={3} > Create a new account </Heading> ); },
Footer() {
const { toSignIn } = useAuthenticator(); return ( <View textAlign="center"> <Button fontWeight="normal" onClick={toSignIn} size="small" variation="link" > Back to Sign In </Button> </View> ); }, },
ConfirmSignUp: {
Header() {
const { tokens } = useTheme(); return ( <Heading padding={`${tokens.space.xl} 0 0 ${tokens.space.xl}`} level={3} > Enter Information: </Heading> ); },
Footer() {
return <Text>Footer Information</Text>; }, }, SetupTotp: { Header() { const { tokens } = useTheme(); return (
<Heading padding={`${tokens.space.xl} 0 0 ${tokens.space.xl}`} level={3} >
Enter Information: </Heading> ); }, Footer() { return <Text>Footer Information</Text>; }, }, ConfirmSignIn: { Header() { const { tokens } = useTheme(); return ( <Heading padding={`${tokens.space.xl} 0 0 ${tokens.space.xl}`} level={3} > Enter Information: </Heading> ); }, Footer() { return <Text>Footer Information</Text>; }, }, ForgotPassword: { Header() { const { tokens } = useTheme(); return ( <Heading padding={`${tokens.space.xl} 0 0 ${tokens.space.xl}`} level={3} > Enter Information: </Heading> ); }, Footer() { return <Text>Footer Information</Text>; }, }, ConfirmResetPassword: { Header() { const { tokens } = useTheme(); return ( <Heading padding={`${tokens.space.xl} 0 0 ${tokens.space.xl}`} level={3} > Enter Information: </Heading> ); }, Footer() { return <Text>Footer Information</Text>; }, }, }; const formFields = { signIn: { username: { placeholder: 'Enter your email', }, }, signUp: { password: { label: 'Password:', placeholder: 'Enter your Password:', isRequired: false, order: 2, }, confirm_password: { label: 'Confirm Password:', order: 1, }, }, forceNewPassword: { password: { placeholder: 'Enter your Password:', }, }, forgotPassword: { username: { placeholder: 'Enter your email:', }, }, confirmResetPassword: { confirmation_code: { placeholder: 'Enter your Confirmation Code:', label: 'New Label', isRequired: false, }, confirm_password: { placeholder: 'Enter your Password Please:', }, }, setupTotp: { QR: { totpIssuer: 'test issuer', totpUsername: 'amplify_qr_test_user', }, confirmation_code: { label: 'New Label', placeholder: 'Enter your Confirmation Code:', isRequired: false, }, }, confirmSignIn: { confirmation_code: { label: 'New Label', placeholder: 'Enter your Confirmation Code:', isRequired: false, }, }, }; export default function App() { return ( <Authenticator formFields={formFields} components={components}> {({ signOut }) => <button onClick={signOut}>Sign out</button>} </Authenticator> ); }

Override Function Calls

You can override the call to signUp, signIn, confirmSignIn, confirmSignUp, forgotPassword and forgotPasswordSubmit functions. To override a call you must create a new services object with an async handle* function that returns an aws-amplify Auth.* promise.

The service object must then be passed into the authenticator component as a services prop. For example, let's imagine you'd like to lowercase the username and the email attributes during signUp. This would be overriden like so:

Sign Up Auto Sign In

When overriding signUp you must include the autoSignIn key and set enabled to true, as show in the example below.

import { Amplify, Auth } from 'aws-amplify';
import { Authenticator } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';
import awsExports from './aws-exports';
Amplify.configure(awsExports);

export default function AuthenticatorWithEmail() {
const services = {
async handleSignUp(formData) { let { username, password, attributes } = formData; // custom username username = username.toLowerCase(); attributes.email = attributes.email.toLowerCase(); return Auth.signUp({ username, password, attributes, autoSignIn: { enabled: true, }, }); }, }; return ( <Authenticator services={services} initialState="signUp"> {({ signOut }) => <button onClick={signOut}>Sign out</button>} </Authenticator> ); }

Each handle* function will return the neccessary values you'll need to make the call to the Auth.* function call. Here is a table of each override function name, and the values returned from formData.

Function CallOverride NameformData Properties
Auth.signUphandleSignUp{username, password, attributes }
Auth.signInhandleSignIn {username, password}
Auth.confirmSignInhandleConfirmSignIn{user, code, mfaType}
Auth.confirmSignUphandleConfirmSignUp{username, code}
Auth.forgotPasswordhandleForgotPassword{username}
Auth.forgotPasswordSubmithandleForgotPasswordSubmit{username, code, password}

Internationalization (I18n)

The Authenticator ships with translations for:

  • en – English (default)
  • zh – Chinese
  • nl – Dutch
  • fr – French
  • de – German
  • he – Hebrew
  • id – Indonesian
  • it – Italian
  • ja – Japanese
  • ko – Korean
  • nb - Norwegian
  • pl – Polish
  • pt – Portuguese
  • ru – Russian
  • es – Spanish
  • sv – Swedish
  • tr – Turkish
  • ua – Ukrainian

These translations can be customized using the Amplify JS' I18n module:

Note: The import path for i18n changed from aws-amplify to aws-amplify/utils in aws-amplify@6

import { I18n } from 'aws-amplify/utils';
import { translations } from '@aws-amplify/ui-react';
I18n.putVocabularies(translations);
I18n.setLanguage('fr');

I18n.putVocabularies({
  fr: {
    'Sign In': 'Se connecter',
    'Sign Up': "S'inscrire",
  },
  es: {
    'Sign In': 'Registrarse',
    'Sign Up': 'Regístrate',
  },
});

The list of available keys are available here.

Confirm Sign Up Page Translations

The confirm sign up page has a few specialized strings that can be translated. These include:

`Your code is on the way. To log in, enter the code we emailed to`

`Your code is on the way. To log in, enter the code we texted to`

`Your code is on the way. To log in, enter the code we sent you. It may take a minute to arrive.`

`It may take a minute to arrive.`
Translations Needed 📖

If you see any missing translations or would like to contribute a new language, we greatly appreciate contributions to translations we have here.

Labels & Text

Using the same techniques as Internationalization (I18n), you can customize the labels and text of the components:

Default Values

Compare the default labels here to those in the customized screens below.

Because I18n manages global translations, customizing these will affect all translations of these strings (including those on this page!).

Sign In

I18n.putVocabulariesForLanguage('en', {
  'Sign In': 'Login', // Tab header
  'Sign in': 'Log in', // Button label
  'Sign in to your account': 'Welcome Back!',
  Username: 'Enter your username', // Username label
  Password: 'Enter your password', // Password label
  'Forgot your password?': 'Reset Password',
});

Sign Up

I18n.putVocabulariesForLanguage('en', {
  'Create Account': 'Register', // Tab header
  'Create a new account': 'New User', // Header text
  'Confirm Password': 'Confirm your password', // Confirm Password label
  Email: 'Enter your email',
  'Phone Number': 'Enter your phone number',
});

Forgot Password

I18n.putVocabulariesForLanguage('en', {
  'Reset your password': 'Forgot your password?',
  'Enter your username': 'Username or Email',
  'Send code': 'Reset my password',
  'Back to Sign In': 'Back to Login',
});

Setup TOTP

I18n.putVocabulariesForLanguage('en', {
  Loading: 'QR code would show here',
  Code: '2FA Code',
  Confirm: 'Confirm 2FA',
  'Back to Sign In': 'Back to Login',
});

Sign Up Fields

The following example customizes the Sign Up screen by:

  • Re-using the default Sign Up form fields
  • Appending a custom "Terms and Conditions" checkbox with a validateCustomSignUp service

Note: In the example code below, preferred_username is not set as an attribute because it has already been defined through Zero Configuration. You may also notice that the acknowledgement field is not being sent. This occurs since acknowledgement is not a known attribute to Cognito. To assign it as a custom attribute instead, the name field must have the custom: prefix.

export default function App() {
  return (
    <Authenticator
      // Default to Sign Up screen
      initialState="signUp"
      // Customize `Authenticator.SignUp.FormFields`
components={{
SignUp: {
FormFields() {
const { validationErrors } = useAuthenticator(); return ( <> {/* Re-use default `Authenticator.SignUp.FormFields` */} <Authenticator.SignUp.FormFields /> {/* Append & require Terms and Conditions field to sign up */} <CheckboxField errorMessage={validationErrors.acknowledgement as string} hasError={!!validationErrors.acknowledgement} name="acknowledgement" value="yes" label="I agree with the Terms and Conditions" /> </> ); }, }, }}
services={{
async validateCustomSignUp(formData) { if (!formData.acknowledgement) { return { acknowledgement: 'You must agree to the Terms and Conditions', }; } }, }} > {({ signOut, user }) => ( <main> <h1>Hello {user.username}</h1> <button onClick={signOut}>Sign out</button> </main> )} </Authenticator> ); }

If you'd like to add an attribute please first consider using the Sign Up Attributes prop. In some instances you may want to add an app-specific attribute. In those cases you can add a new form element to the Sign Up form fields. Be aware the HTML name attribute on the new form field must match the name of the Cognito attribute. If the cognito attribute is a custom attribute it must have the custom: prefix in the HTML attribute name.

  const formFields = {
    signUp: {
      email: {
        order:1
      },
      password: {
        order: 2
      },
      confirm_password: {
        order: 3
      },
      'custom:your_custom_attribute': {
        order: 4
      }
    },
  }

Force New Password Fields

The following example customizes the Force New Password screen by:

  • Re-using the default Force New Password form fields
  • Appending a custom "Zone Info" text field
<Authenticator
      initialState="signUp"
      components={{
        ForceNewPassword: {
          FormFields() {
            return (
<>
<Authenticator.ForceNewPassword.FormFields />
<TextField label="Zone Info" id="12233" placeholder="Zone Info" name="zoneinfo" type="text" ></TextField>
</> ); }, }, }} > {({ signOut }) => <button onClick={signOut}>Sign out</button>} </Authenticator> ); }

Sign Up Field Order

The authenticator allows a custom order of sign up fields on the Sign Up page.

Order is determined by a formFields prop that is passed into the Authenticator component. This prop will have the signUp key with a list of all the input fields. Each input field will have an order key that specifies which order it will be displayed on the page.

In the example below the order will be set as email, family_name, birthdate, preferred_username, password and finally confirm_password.

Note: Fields that do not have a order key will be displayed at the bottom of the Sign Up page. The order key can also be combined with other form field updates. In addition, typically attributes added to the sign up page have already been inferred through Zero Configuration. However, you can explicitly set the sign up attributes prop to add these to the sign up page if needed.


const formFields = {
signUp: {
email: {
order:1
},
family_name: {
order: 2
},
preferred_username: { order: 4 }, birthdate: { order: 3 }, password: { order: 5 }, confirm_password: { order: 6 } }, } // Adding the signUpAttributes prop is typically not needed since attributes are inferred via Zero Configuration. // For the sake of this example they have been explicitly added so you can copy and paste this into your own application and see it work. const signUpAttributes={['birthdate', 'family_name', 'preferred_username']} export default function App() { return ( <Authenticator formFields={formFields} signUpAttributes={signUpAttributes}> {({ signOut }) => <button onClick={signOut}>Sign out</button>} </Authenticator> ); }

Form Field Customization

The Authenticator allows for customization of multiple aspects of the form fields. The sections below will describe several use cases, on how to modify these fields.

Overall, the following attributes are allowed to be modified on any input as described in the labels and placeholder section:

placeholder label

Additionally, you'll be able to show or hide the label of each form field by using labelHidden and set a field to required or not required with isRequired.

For customers wishing to change a phone number field, a new dialCode and dialCodeList key are now available as described in the dialCode and dialCodeList.

For a full list of component names and field names can be found in the input form table.

Updating labels, placeholders, required fields and showing labels

You can customize any label, placeholder, set a field as required or not required, and hide or show labels by configuring the formFields props, and passing it into the Authenticator component. To use this feature create a formFields prop and include the component name as a key. Inside that object you can list all the inputs you'd like to change by their name. Inputs can have additional client side validation by following HTML form validation standards.

The following example customizes the Sign In page by:

  • Updating the placeholder with placeholder.
  • Setting required to true with isRequired, which is also the default for this field.
  • Updating the label text with label.
  • Show the label using labelHidden set to false.

Note: On the sign in page the input name is always username, regardless of the login mechanism type.


const formFields = {
signIn: {
username: {
placeholder: 'Enter Your Email Here',
isRequired: true,
label: 'Email:'
},
},
}
export default function App() { return ( <Authenticator formFields={formFields}> {({ signOut }) => <button onClick={signOut}>Sign out</button>} </Authenticator> ); }

Default international dial code

Default Dial code customization is available via the dialCode form field key.

The following example will set the default dial code to +227 on the Sign Up and Sign In page.


const formFields = {
signIn: {
username: {
dialCode: '+227'
},
},
signUp: {
phone_number: {
dialCode: '+227'
}, }, } export default function App() { return ( <Authenticator formFields={formFields}> {({ signOut }) => <button onClick={signOut}>Sign out</button>} </Authenticator> ); }

Change dial code list

If needed, you can update the list of dial codes shown to the user by assigning an array of dial codes to the dialCodeList.

In this example, only four dial codes are show in the drop down list for the sign in and sign up pages.

Note: Make sure to add the plus sign to each dial code in the dialCodeList.


const formFields = {
signIn: {
username: {
dialCodeList: ['+1', '+123', '+227', '+229']
},
},
signUp: {
phone_number: {
dialCodeList: ['+1', '+123', '+227', '+229']
}, }, } export default function App() { return ( <Authenticator formFields={formFields}> {({ signOut }) => <button onClick={signOut}>Sign out</button>} </Authenticator> ); }

Input Form Field Names Table

Here are the various components and input names that are available for customization.

Component NameForm Field Names
signInusername password
signUpemail phone_number username password confirm_password preferred_username birthdate family_name middle_name given_name name nickname profile website
confirmSignUpconfirmation_code
forgotPasswordusername
confirmResetPasswordconfirmation_code password confirm_password
forceNewPasswordpassword confirm_password
setupTotpconfirmation_code
confirmSignInconfirmation_code
confirmVerifyUserconfirmation_code

Note: Custom sign up attributes not listed in this table are customizable. Use the form field name as the key.

Update Setup TOTP QR Issuer and Username

When setting up TOTP you can customize the issuer and username that will be shown in TOTP applications. This can be done by adding the formFields prop to the Authenticator component with a setupTotp key. The setupTotp should have a QR key with a totpIssuer and or totpUsername as seen in the example below.

Note: Unless changed, the default issuer is AWSCognito and username will be the current user.username for the user signing up.


const formFields = {
setupTotp: {
QR: {
totpIssuer: 'test issuer',
totpUsername: 'amplify_qr_test_user',
},
},
}
export default function App() { return ( <Authenticator formFields={formFields}> {({ signOut }) => <button onClick={signOut}>Sign out</button>} </Authenticator> ); }

Styling

You can customize the Authenticator's default style by using CSS variables.

CSS style

The example below uses a <style> tag to change the appearance of some of the components used for the Authenticator:


[data-amplify-authenticator] {
  --amplify-components-authenticator-router-box-shadow: 0 0 16px var(--amplify-colors-overlay-10);
  --amplify-components-authenticator-router-border-width: 0;
  --amplify-components-authenticator-form-padding: var(--amplify-space-medium) var(--amplify-space-xl) var(--amplify-space-xl);
  --amplify-components-button-primary-background-color: var(--amplify-colors-neutral-100);
  --amplify-components-fieldcontrol-focus-box-shadow: 0 0 0 2px var(--amplify-colors-purple-60);
  --amplify-components-tabs-item-active-border-color: var(--amplify-colors-neutral-100);
  --amplify-components-tabs-item-color: var(--amplify-colors-neutral-80);
  --amplify-components-tabs-item-active-color: var(--amplify-colors-purple-100);
  --amplify-components-button-link-color: var(--amplify-colors-purple-80);
}

Theme Provider Theme

Below is an example of updating the style of the Authenticator by using the ThemeProvider theme object. To do this, you must surround the Authenticator in the ThemeProvider.

Then create a theme object, with all your font and color updates. Feel free to use design tokens, as a way of designing your theme further.

import {
  Authenticator,
  ThemeProvider,
  Theme,
  useTheme,
  View,
} from '@aws-amplify/ui-react';
export function AuthStyle() {
  const { tokens } = useTheme();
  const theme: Theme = {
    name: 'Auth Example Theme',
    tokens: {
      components: {
        authenticator: {
          router: {
            boxShadow: `0 0 16px ${tokens.colors.overlay['10']}`,
            borderWidth: '0',
          },
          form: {
            padding: `${tokens.space.medium} ${tokens.space.xl} ${tokens.space.medium}`,
          },
        },
        button: {
          primary: {
            backgroundColor: tokens.colors.neutral['100'],
          },
          link: {
            color: tokens.colors.purple['80'],
          },
        },
        fieldcontrol: {
          _focus: {
            boxShadow: `0 0 0 2px ${tokens.colors.purple['60']}`,
          },
        },
        tabs: {
          item: {
            color: tokens.colors.neutral['80'],
            _active: {
              borderColor: tokens.colors.neutral['100'],
              color: tokens.colors.purple['100'],
            },
          },
        },
      },
    },
  };

  return (
    <ThemeProvider theme={theme}>
      <View padding="xxl">
        <Authenticator />
      </View>
    </ThemeProvider>
  );
}

If you have TypeScript enabled, all the object keys will be present when creating the theme object. This will help speed up your development time while creating themes.

Additional CSS Styling

You can also override the authenticator's amplify-* classes. For example, if you'd like to update the primary color of your submit button you can override the amplify-button class.

.amplify-button--primary {
  background: linear-gradient(
    to right,
    var(--amplify-colors-green-80),
    var(--amplify-colors-orange-40)
  );
}

Amplify open source software, documentation and community are supported by Amazon Web Services.

© 2024 Amazon Web Services, Inc. and its affiliates. All rights reserved. View the site terms and privacy policy.

Flutter and the related logo are trademarks of Google LLC. We are not endorsed by or affiliated with Google LLC.