Build Login with Password
Before you start
You need:
An Auth0 development tenant with Universal Login configured.
A custom-domain-configured application.
A development app or a sample app (like the React sample app) running on your localhost
A database connection that uses passwords.
By the end of this guide, you'll have an identity-first flow with a customized Login screen. To learn more, read the Getting Started guide and visit the SDK reference guide.
Setup
In your Auth0 Dashboard, set up Universal Login, Identifier First Authentication, and a Database Connection that uses passwords.
Run a single-page application to build custom login screens. To understand the context for Advanced Customizations interfaces, clone our boilerplate app: git clone https://github.com/auth0/auth0-acul-react-boilerplate
Install the ACUL SDK. After cloning the react boilerplate, change the directory to the auth0-acul-react-boilerplate
folder and install the SDK.
// open the directory where you git clone the boilerplate
cd auth0-acul-react-boilerplate && npm i
// Install the ACUL JS SDK
npm install @auth0/auth0-acul-js
feedbackSection.helpful
1. Build the login screen

Below is a full sample of the Screen.
import { ChangeEvent } from "react";
import { Login as ScreenProvider } from "@auth0/auth0-acul-js";
// UI Components
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Text } from "@/components/ui/text";
import { Link } from "@/components/ui/link";
import {
CardHeader,
CardTitle,
CardDescription,
CardContent,
} from "@/components/ui/card";
export default function Login() {
// Initialize the SDK for this screen
const screenProvider = new ScreenProvider();
// Handle the submit action
const formSubmitHandler = (event: ChangeEvent<HTMLFormElement>) => {
event.preventDefault();
// grab the values from the form
const identifierInput = event.target.querySelector(
"input#identifier"
) as HTMLInputElement;
const passwordInput = event.target.querySelector(
"input#password"
) as HTMLInputElement;
// Call the SDK
screenProvider.login({
username: identifierInput?.value,
password: passwordInput?.value,
});
};
// Render the form
return (
<form noValidate onSubmit={formSubmitHandler}>
<CardHeader>
<CardTitle className="mb-2 text-3xl font-medium text-center">
{screenProvider.screen.texts?.title ?? "Welcome"}
</CardTitle>
<CardDescription className="mb-8 text-center">
{screenProvider.screen.texts?.description ?? "Login to continue"}
</CardDescription>
</CardHeader>
<CardContent>
<div className="mb-2 space-y-2">
<Label htmlFor="identifier">
{screenProvider.screen.texts?.emailPlaceholder ??
"Enter your email"}
</Label>
<Input
type="text"
id="identifier"
name="identifier"
defaultValue={
screenProvider.screen.data?.username ??
screenProvider.untrustedData.submittedFormData?.username
}
/>
</div>
<div className="mb-2 space-y-2">
<Label htmlFor="identifier">
{screenProvider.screen.texts?.passwordPlaceholder ?? "Password"}
</Label>
<Input type="password" id="password" name="password" />
</div>
<Button type="submit" className="w-full">
{screenProvider.screen.texts?.buttonText ?? "Continue"}
</Button>
<Text className="mb-2">
{screenProvider.screen.texts?.footerText ?? "Don't have an account yet?"}
<Link className="ml-1" href={screenProvider.screen.signupLink ?? "#"}>
{screenProvider.screen.texts?.footerLinkText ?? "Create your account"}
</Link>
</Text>
<Text>
Need Help?
<Link className="ml-1" href={screenProvider.screen.resetPasswordLink ?? "#"}>
{screenProvider.screen.texts?.forgottenPasswordText ?? "Forgot your Password?"}
</Link>
</Text>
</CardContent>
</form>
);
}
feedbackSection.helpful
Import and initialize the SDK
In the auth0-acul-react-boilerplate/src
folder, create a folder called screens
and a file called Login.tsx
. Import the SDK and in the React component initialize the SDK for the screen.
import { Login as ScreenProvider } from "@auth0/auth0-acul-js";
export default function Login() {
// Initialize the SDK for this screen
const screenProvider = new ScreenProvider();
...
}
feedbackSection.helpful
Use the SDK to access properties and methods on the screen
Using the SDK you can access the properties and methods of the screen. The Auth0 ACUL JS SDK provides properties and methods to access the data.
<form noValidate onSubmit={formSubmitHandler}>
...
<CardContent>
<div className="mb-2 space-y-2">
<Label htmlFor="identifier">
{screenProvider.screen.texts?.emailPlaceholder ??
"Enter your email"}
</Label>
<Input
type="text"
id="identifier"
name="identifier"
defaultValue={
screenProvider.screen.data?.username ??
screenProvider.untrustedData.submittedFormData?.username
}
/>
</div>
<div className="mb-2 space-y-2">
<Label htmlFor="identifier">
{screenProvider.screen.texts?.passwordPlaceholder ?? "Password"}
</Label>
<Input type="password" id="password" name="password" />
</div>
<Button type="submit" className="w-full">
{screenProvider.screen.texts?.buttonText ?? "Continue"}
</Button>
...
</CardContent>
</form>
);
}
feedbackSection.helpful
Call the submit action
Using the SDK, submit the data captured in the screen to the server. The server process this data and will route the user to the next step in the flow. If there are errors, this screen is reloaded, allowing you to display them to the user. Errors are accessed from the SDK.
const formSubmitHandler = (event: ChangeEvent<HTMLFormElement>) => {
event.preventDefault();
// grab the value from the form
const identifierInput = event.target.querySelector(
"input#identifier"
) as HTMLInputElement;
// Call the SDK
screenProvider.login({ username: identifierInput?.value });
};
feedbackSection.helpful
2: Configure ACUL to use local assets
Use Auth0 CLI, Terraform, or the Management API to enable ACUL. For details about what can be configured, read Configure ACUL Screens.
In the root directory of your project, create a settings
folder and include in it a {SCREENNAME}.json
file.
//settings.json
{
"rendering_mode": "advanced",
"context_configuration": [
"screen.texts"
],
"default_head_tags_disabled": false,
"head_tags": [
{
"attributes": {
"async": true,
"defer": true,
"integrity": [
"ASSET_SHA"
],
"src": "http://127.0.0.1:8080/index.js"
},
"tag": "script"
},
{
"attributes": {
"href": "http://127.0.0.1:8080/index.css",
"rel": "stylesheet"
},
"tag": "link"
}
]
}
feedbackSection.helpful
auth0 ul customize --rendering-mode advanced --prompt {SCREENNAME} --screen {SCREENNAME} --settings-file ./settings/{SCREENNAME}.json
feedbackSection.helpful
In the root directory of your project, create a login-id.json
file:
//login-id.json
{
"rendering_mode": "advanced",
"context_configuration": [
"screen.texts"
],
"default_head_tags_disabled": false,
"head_tags": [
{
"attributes": {
"async": true,
"defer": true,
"integrity": [
"ASSET_SHA"
],
"src": "http://127.0.0.1:8080/index.js"
},
"tag": "script"
},
{
"attributes": {
"href": "http://127.0.0.1:8080/index.css",
"rel": "stylesheet"
},
"tag": "link"
}
]
}
feedbackSection.helpful
Enable ACUL with Auth0 Terraform
prompts:
identifier_first: true
universal_login_experience: classic
mfa-login-options:
pageTitle: 'Log in to ${clientName}'
authenticatorNamesSMS: 'SMS'
screenRenderers:
- login-id:
login-id: ./prompts/screenRenderSettings/login-id.json
feedbackSection.helpful
You can use Auth0 Management API to enable ACUL
curl --location --request PATCH 'https://{YOUR-CUSTOM-DOMAIN}/api/v2/prompts/{YOUR-PROMPT}/screen/{YOUR-SCREEN}/rendering' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <API TOKEN>' \
--data '{
"rendering_mode": "advanced",
"context_configuration": [
"branding.settings",
"organization.branding",
"screen.texts",
"tenant.name",
"tenant.friendly_name",
"tenant.enabled_locales",
"untrusted_data.submitted_form_data",
"untrusted_data.authorization_params.ui_locales",
"untrusted_data.authorization_params.login_hint",
"untrusted_data.authorization_params.screen_hint"
],
"default_head_tags_disabled": false,
"head_tags": [
{
"tag": "script",
"attributes": {
"src": "http://127.0.0.1:8080/index.js",
"defer": true
}
},
{
"tag": "link",
"attributes": {
"rel": "stylesheet",
"href": "http://127.0.0.1:8080/index.css"
}
},
{
"tag": "meta",
"attributes": {
"name": "viewport",
"content": "width=device-width, initial-scale=1"
}
}
]
}'
feedbackSection.helpful
Test your configuration on a local server
ACUL requires assets to be hosted on a public URL. Run a local server and test your assets before deploying them.
npm run build
cd dist
npx serve -p 8080 // serve the assets on your local machine
feedbackSection.helpful
3: Deploy the assets and update your tenant configuration
Advanced Customization for Universal Login works with all modern Javascript bundlers. like Vite and Webpack. For more information, read Deploy Advanced Customizations to Production.
For more information about deploying ACUL to your tenant, read Configure ACUL Screens.
Related content
Read... | To learn... |
---|---|
Advanced Customizations for Universal Login | How Advanced Customizations work. |
Getting Started with Advanced Customizations | Getting Started basics for Advanced Customizations |
Advanced Customizations for Universal Login: Screens | A list of all screens available for Advanced Customizations. |