Documentation Index Fetch the complete documentation index at: https://docs-staging-quickstart-revamp.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
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 a passwordless connection.
By the end of this flow, you’ll have a customized Passwordless login screen with the option for email or SMS.
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.
# Clone the ACUL sample application into the root folder of your project
git clone https://github.com/auth0-samples/auth0-acul-samples.git
# Change directory to install the ACUL sample application
cd auth0-acul-samples && npm i
Option 1: Build the Passwordless Login screen for email
Below is a full sample of the Screen. This example uses Shadcn components .
import { ChangeEvent } from "react" ;
import { LoginPasswordlessEmailCode as ScreenProvider } from "@auth0/auth0-acul-js" ;
// UI Components
import { Label } from "@/components/ui/label" ;
import { Button } from "@/components/ui/button" ;
import { Text } from "@/components/ui/text" ;
import { Link } from "@/components/ui/link" ;
import { Input } from "@/components/ui/input" ;
import { REGEXP_ONLY_DIGITS_AND_CHARS } from "input-otp"
import {
InputOTP ,
InputOTPGroup ,
InputOTPSlot ,
} from "@/components/ui/input-otp"
import {
CardHeader ,
CardTitle ,
CardDescription ,
CardContent ,
} from "@/components/ui/card" ;
export default function LoginPasswordlessEmailCode () {
// Initialize the SDK for this screen
const screenProvider = new ScreenProvider ();
// Handle the submit action
const formSubmitHandler = ( event : ChangeEvent < HTMLFormElement >) => {
event . preventDefault ();
// grab the value from the form
const OtpInput = event . target . querySelector (
"input#otp_code"
) as HTMLInputElement ;
const identifierInput = event . target . querySelector (
"input#identifier"
) as HTMLInputElement ;
// Call the SDK
screenProvider . submitCode ({
username: identifierInput ?. value ,
code: OtpInput ?. value
});
};
// Render the form
return (
< form noValidate onSubmit = { formSubmitHandler } >
< CardHeader >
< CardTitle className = "mb-2 text-3xl font-medium text-center" >
{ screenProvider . screen . texts ?. title ?? "Verify yourself" }
</ CardTitle >
< CardDescription className = "mb-8 text-center" >
{ screenProvider . screen . texts ?. description ??
"Enter the code sent to the email below" }
</ CardDescription >
</ CardHeader >
< CardContent >
< Text className = "mb-4 text-large" >
< span className = "inline-block" >
Continue as
< span className = "inline-block ml-1 font-bold" >
{ screenProvider . screen . data ?. username } .
</ span >
</ span >
< Link
href = { screenProvider . screen . links . editIdentifierLink ?? "#" }
className = "ml-2"
>
{ screenProvider . screen . texts ?. editText ?? "Edit Email" }
</ Link >
</ Text >
< Input
type = "hidden"
name = "identifier"
id = "identifier"
value = { screenProvider . screen . data ?. username }
/>
< Label htmlFor = "otp_code" >
{ screenProvider . screen . texts ?. placeholder ?? "Enter the OTP Code" }
</ Label >
< div className = "flex items-center w-full space-y-2" >
< InputOTP
maxLength = { 6 }
pattern = { REGEXP_ONLY_DIGITS_AND_CHARS }
id = "otp_code"
name = "otp_code"
>
< InputOTPGroup >
< InputOTPSlot index = { 0 } />
< InputOTPSlot index = { 1 } />
< InputOTPSlot index = { 2 } />
< InputOTPSlot index = { 3 } />
< InputOTPSlot index = { 4 } />
< InputOTPSlot index = { 5 } />
</ InputOTPGroup >
</ InputOTP >
< Button type = "submit" className = "ml-2" >
{ screenProvider . screen . texts ?. buttonText ?? "Verify" }
</ Button >
</ div >
< Text >
{ screenProvider . screen . texts ?. resendText ?? "Didn't get the OTP?" }
< Link className = "ml-1" href = "#" onClick = { screenProvider . resendCode } >
{ screenProvider . screen . texts ?. resendActionText ?? "Send again." }
</ Link >
</ Text >
</ CardContent >
</ form >
);
}
See all 111 lines
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 { LoginPasswordlessEmailCode as ScreenProvider } from "@auth0/auth0-acul-js" ;
export default function LoginPasswordlessEmailCode () {
// Initialize the SDK for this screen
const screenProvider = new ScreenProvider ();
...
}
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 >
< Text className = "mb-4 text-large" >
< span className = "inline-block" >
Continue as
< span className = "inline-block ml-1 font-bold" >
{ screenProvider . screen . data ?. username } .
</ span >
</ span >
< Link
href = { screenProvider . screen . links . editIdentifierLink ?? "#" }
className = "ml-2"
>
{ screenProvider . screen . texts ?. editText ?? "Edit Email" }
</ Link >
</ Text >
< Input
type = "hidden"
name = "identifier"
id = "identifier"
value = { screenProvider . screen . data ?. username }
/>
< Label htmlFor = "otp_code" >
{ screenProvider . screen . texts ?. placeholder ?? "Enter the OTP Code" }
</ Label >
< div className = "flex items-center w-full space-y-2" >
< InputOTP
maxLength = { 6 }
pattern = { REGEXP_ONLY_DIGITS_AND_CHARS }
id = "otp_code"
name = "otp_code"
>
< InputOTPGroup >
< InputOTPSlot index = { 0 } />
< InputOTPSlot index = { 1 } />
< InputOTPSlot index = { 2 } />
< InputOTPSlot index = { 3 } />
< InputOTPSlot index = { 4 } />
< InputOTPSlot index = { 5 } />
</ InputOTPGroup >
</ InputOTP >
< Button type = "submit" className = "ml-2" >
{ screenProvider . screen . texts ?. buttonText ?? "Verify" }
</ Button >
</ div >
...
</ CardContent >
</ form >
);
}
See all 51 lines
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 OtpInput = event . target . querySelector (
"input#otp_code"
) as HTMLInputElement ;
const identifierInput = event . target . querySelector (
"input#identifier"
) as HTMLInputElement ;
// Call the SDK
screenProvider . submitCode ({
username: identifierInput ?. value ,
code: OtpInput ?. value
});
Option 2: Build the Passwordless Login screen for SMS
Below is a full sample of the Screen.
import { ChangeEvent } from "react" ;
import { LoginPasswordlessSmsOtp as ScreenProvider } from "@auth0/auth0-acul-js" ;
// UI Components
import { Label } from "@/components/ui/label" ;
import { Button } from "@/components/ui/button" ;
import { Text } from "@/components/ui/text" ;
import { Link } from "@/components/ui/link" ;
import { Input } from "@/components/ui/input" ;
import { REGEXP_ONLY_DIGITS_AND_CHARS } from "input-otp"
import {
InputOTP ,
InputOTPGroup ,
InputOTPSlot ,
} from "@/components/ui/input-otp"
import {
CardHeader ,
CardTitle ,
CardDescription ,
CardContent ,
} from "@/components/ui/card" ;
export default function LoginPasswordlessSmsOtp () {
// Initialize the SDK for this screen
const screenProvider = new ScreenProvider ();
// Handle the submit action
const formSubmitHandler = ( event : ChangeEvent < HTMLFormElement >) => {
event . preventDefault ();
// grab the value from the form
const OtpInput = event . target . querySelector (
"input#otp_code"
) as HTMLInputElement ;
const identifierInput = event . target . querySelector (
"input#identifier"
) as HTMLInputElement ;
// Call the SDK
screenProvider . submitOTP ({
username: identifierInput ?. value ,
code: OtpInput ?. value
});
};
// Render the form
return (
< form noValidate onSubmit = { formSubmitHandler } >
< CardHeader >
< CardTitle className = "mb-2 text-3xl font-medium text-center" >
{ screenProvider . screen . texts ?. title ?? "Verify yourself" }
</ CardTitle >
< CardDescription className = "mb-8 text-center" >
{ screenProvider . screen . texts ?. description ??
"Enter the code sent to the phone below" }
</ CardDescription >
</ CardHeader >
< CardContent >
< Text className = "mb-4 text-large" >
< span className = "inline-block" >
Continue as
< span className = "inline-block ml-1 font-bold" >
{ screenProvider . screen . data ?. username } .
</ span >
</ span >
< Link
href = { screenProvider . screen . links ?. edit_identifier ?? "#" }
className = "ml-2"
>
{ screenProvider . screen . texts ?. editText ?? "Edit Phone" }
</ Link >
</ Text >
< Input
type = "hidden"
name = "identifier"
id = "identifier"
value = { screenProvider . screen . data ?. username }
/>
< Label htmlFor = "otp_code" >
{ screenProvider . screen . texts ?. placeholder ?? "Enter the OTP Code" }
</ Label >
< div className = "flex items-center w-full space-y-2" >
< InputOTP
maxLength = { 6 }
pattern = { REGEXP_ONLY_DIGITS_AND_CHARS }
id = "otp_code"
name = "otp_code"
>
< InputOTPGroup >
< InputOTPSlot index = { 0 } />
< InputOTPSlot index = { 1 } />
< InputOTPSlot index = { 2 } />
< InputOTPSlot index = { 3 } />
< InputOTPSlot index = { 4 } />
< InputOTPSlot index = { 5 } />
</ InputOTPGroup >
</ InputOTP >
< Button type = "submit" className = "ml-2" >
{ screenProvider . screen . texts ?. buttonText ?? "Verify" }
</ Button >
</ div >
< Text >
{ screenProvider . screen . texts ?. resendText ?? "Didn't get the OTP?" }
< Link className = "ml-1" href = "#" onClick = { screenProvider . resendOTP } >
{ screenProvider . screen . texts ?. resendActionText ?? "Send again." }
</ Link >
</ Text >
</ CardContent >
</ form >
);
}
See all 111 lines
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 { LoginPasswordlessSmsOtp as ScreenProvider } from "@auth0/auth0-acul-js" ;
export default function LoginPasswordlessSmsOtp () {
// Initialize the SDK for this screen
const screenProvider = new ScreenProvider ();
...
}
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 >
< Text className = "mb-4 text-large" >
< span className = "inline-block" >
Continue as
< span className = "inline-block ml-1 font-bold" >
{ screenProvider . screen . data ?. username } .
</ span >
</ span >
< Link
href = { screenProvider . screen . links ?. edit_identifier ?? "#" }
className = "ml-2"
>
{ screenProvider . screen . texts ?. editText ?? "Edit Phone" }
</ Link >
</ Text >
< Input
type = "hidden"
name = "identifier"
id = "identifier"
value = { screenProvider . screen . data ?. username }
/>
< Label htmlFor = "otp_code" >
{ screenProvider . screen . texts ?. placeholder ?? "Enter the OTP Code" }
</ Label >
< div className = "flex items-center w-full space-y-2" >
< InputOTP
maxLength = { 6 }
pattern = { REGEXP_ONLY_DIGITS_AND_CHARS }
id = "otp_code"
name = "otp_code"
>
< InputOTPGroup >
< InputOTPSlot index = { 0 } />
< InputOTPSlot index = { 1 } />
< InputOTPSlot index = { 2 } />
< InputOTPSlot index = { 3 } />
< InputOTPSlot index = { 4 } />
< InputOTPSlot index = { 5 } />
</ InputOTPGroup >
</ InputOTP >
< Button type = "submit" className = "ml-2" >
{ screenProvider . screen . texts ?. buttonText ?? "Verify" }
</ Button >
</ div >
...
</ CardContent >
</ form >
);
}
See all 51 lines
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 OtpInput = event . target . querySelector (
"input#otp_code"
) as HTMLInputElement ;
const identifierInput = event . target . querySelector (
"input#identifier"
) as HTMLInputElement ;
// Call the SDK
screenProvider . submitCode ({
username: identifierInput ?. value ,
code: OtpInput ?. value
});
Use Auth0 CLI, Terraform, or the Management API to enable ACUL. For details about what can be configured, read Configure ACUL Screens .
Auth0 CLI (Recommended)
Auth0 Terraform
Auth0 Management API
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"
],
"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"
}
]
}
See all 27 lines
Enable ACUL with Auth0 CLI: auth0 ul customize --rendering-mode advanced --prompt {SCREENNAME} --screen {SCREENNAME} --settings-file ./settings/{SCREENNAME}.json
In the root directory of your project, create a login-id.json file: //login-id.json
{
"rendering_mode" : "advanced" ,
"context_configuration" : [
"screen.texts"
],
"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"
}
]
}
See all 27 lines
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
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"
],
"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"
}
}
]
}'
See all 41 lines
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.
// Creates the local assets
npm run build
cd dist
// Serves the assets from localhost
npx serve - p 8080 -- cors
Step 4: 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 and Host Advanced Customizations .
For more information about deploying ACUL to your tenant, read Configure ACUL Screens.
Related content
For more information about screens that can be customized, read Advanced Customization JS SDK Reference .