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]}>
© 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.
Use resetPassword
in place of forgotPassword
in versions 5 and earlier of @aws-amplify/ui-react
.
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:
In @aws-amplify/ui-react
version 6, Auth
function calls are imported directly as shown below.
import { Authenticator } from '@aws-amplify/ui-react';
import { signUp, SignUpInput } from 'aws-amplify/auth';
export default function App() {
const services = {
async handleSignUp(input: SignUpInput) {
// custom username and email
const { username, password, options } = input;
const customUsername = username.toLowerCase();
const customEmail = options?.userAttributes?.email.toLowerCase();
return signUp({
username: customUsername,
password,
options: {
...input.options,
userAttributes: {
...input.options?.userAttributes,
email: customEmail,
},
},
});
},
};
return (
<Authenticator services={services} initialState="signUp">
{({ signOut }) => <button onClick={signOut}>Sign out</button>}
</Authenticator>
);
}
If you're overriding signUp
in @aws-amplify/ui-react
version 5 or earlier, you must include the autoSignIn
key and set enabled
to true, as shown in the example below.
In @aws-amplify/ui-react
version 5 and earlier, Auth
function calls are imported from the Auth
object.
import { Auth } from 'aws-amplify';
import { Authenticator } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';
export default function App() {
const services = {
async handleSignUp(input) {
let { username, password, attributes } = input;
// custom username and email
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 accepts as input the expected input of its corresponding Auth
function, allowing you to override the Auth
function call from within the handle*
function. Here is a table of each override function name, and the values passed as input
.
Auth Function Call | Override Name | input Properties |
---|---|---|
signUp | handleSignUp | {username, password} |
signIn | handleSignIn | {username, password} |
confirmSignIn | handleConfirmSignIn | {challengeResponse} |
confirmSignUp | handleConfirmSignUp | {username, confirmationCode} |
resetPassword | handleForgotPassword | {username} |
confirmResetPassword | handleForgotPasswordSubmit | {username, newPassword, confirmationCode} |
Function Call | Override Name | formData Properties |
---|---|---|
Auth.signUp | handleSignUp | {username, password, attributes} |
Auth.signIn | handleSignIn | {username, password} |
Auth.confirmSignIn | handleConfirmSignIn | {user, code, mfaType} |
Auth.confirmSignUp | handleConfirmSignUp | {username, code} |
Auth.forgotPassword | handleForgotPassword | {username} |
Auth.forgotPasswordSubmit | handleForgotPasswordSubmit | {username, code, password} |
Internationalization (I18n)
The Authenticator
ships with translations for:
en
– English (default)zh
– Chinesenl
– Dutchfr
– Frenchde
– Germanhe
– Hebrewid
– Indonesianit
– Italianja
– Japaneseko
– Koreannb
- Norwegianpl
– Polishpt
– Portugueseru
– Russianes
– Spanishsv
– Swedishth
- Thaitr
– Turkishua
– Ukrainian
These translations can be customized using the Amplify JS' I18n
module:
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.`
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 thecustom:
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.
Note: Specifying formFields
for a given field will overwrite any default attributes. To include defaults, you must re-specify them as shown below.
The following example customizes the Sign In page by:
- Updating the placeholder with
placeholder
. - Setting required to true with
isRequired
.username
is required by default, but as mentioned above, default attributes will be overwritten and must be re-declared when usingformFields
. - Updating the label text with
label
. - Show the label using
labelHidden
set tofalse
.
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 Name | Form Field Names |
---|---|
signIn | username password |
signUp | email phone_number username password confirm_password preferred_username birthdate family_name middle_name given_name name nickname profile website |
confirmSignUp | confirmation_code |
forgotPassword | username |
confirmResetPassword | confirmation_code password confirm_password |
forceNewPassword | password confirm_password |
setupTotp | confirmation_code |
confirmSignIn | confirmation_code |
confirmVerifyUser | confirmation_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)
);
}