You can customize pages by providing a page template created with the Liquid template language. With page templates, you can define the content displayed around Universal Login prompts, such as the login box or an challenge. As the same page template is used for all login flow pages, this method of customization allows you to easily implement a consistent, branded experience for users. To use customized page templates, you must configure a Custom Domain for your tenant. Further, you can only update Universal Login page templates with the Management API.
The term prompt refers to a specific step of the login flow, such as the sign-up page or an MFA challenge. The variables and code samples on this page may use the term prompt or the term widget. While these terms are synonymous in the context of Universal Login, they are not interchangeable within your code.  To ensure successful customization, verify you are using the appropriate term listed for any elements you add to your code.

Page template requirements

When creating a Universal Login page template, you must include the following tags:
TagDescription
auth0:widgetContains HTML for the prompt displayed on every page of the login flow, such as the Login page or Reset Password page
auth0:headContains the tags required for rendering the prompt
To center the prompt on the page, add class="_widget-auto-layout" to the <body> element. You can omit this attribute to manually position the prompt as needed.
Page template limitations:
  • CSS class names change each time Auth0 builds the project. Custom CSS that targets these classes will break with each new build.
  • The HTML structure of Universal Login pages is subject to change. Avoid customizations that rely on the HTML structure to prevent any interruptions.
To learn more, review CSS customization.
Example template:
The following example demonstrates the simplest Universal Login page template you can create with the required tags:
<!DOCTYPE html>
{% assign resolved_dir = dir | default: "auto" %}
<html lang="{{locale}}" dir="{{resolved_dir}}">
  <head>
    {%- auth0:head -%}
  </head>
  <body class="_widget-auto-layout">
    {%- auth0:widget -%}
  </body>
</html>
If you use Storybook to view your template, be aware that the <script> tag breaks the rendering as it cannot parse these tags correctly.  As a workaround, use backticks (`) and plus sign (+) characters to properly inject the <script> tag into your template code.Example:<scr`+`ipt>console.log("test");</scr`+`ipt>

Page template variables

Page templates support a variety of context variables that impact how a page is rendered. For example, you can use these variables to:
  • Render different content depending on the application associated with the login flow. For example, you may manage two brands that require different page designs.
  • Render different content depending on the specific prompt. For example, you may want to add information about what your application offers on the Login page but prefer the MFA flow to only display the MFA challenge prompt.
  • Add a footer with user support information, such as links to your support page or contact information.

Available variables

Page templates support the following variables:

Application

VariableDescriptionExample
application.idYour application client IDXXXXXXXXXXXXXXXXXXXXXXXXX
application.nameThe name of your applicationMy Application
application.logo_urlURL of the application logohttps://example.com/mylogo.png
application.metadataYour application metadata
{
  "attribute1": "value",
  "attribute2": "value",
  "attribute3": "value"
}

Branding

VariableDescriptionExample
branding.logo_urlURL of your application logohttps://example.com/mylogo.png
branding.colors.primaryYour primary branding color#000000
branding.colors.page_backgroundBackground color for Universal Login pages#FFFFFF

Tenant

VariableDescriptionExample
tenant.friendly_nameYour tenant’s display nameMy Tenant
tenant.support_emailSupport email address for your tenantsupport@example.com
tenant.support_urlSupport page URL for your tenanthttps://example.com/support
tenant.enabled_localesComma-separated list of locales enabled for your tenanten, es

Organizations

The following variables refer to the Auth0 Organizations feature.
VariableDescriptionExample
organization.idID of Organizationorg_XXXXXXXXXXXXXXX
organization.display_nameDisplay name of OrganizationMy Organization
organization.nameInternal name of Organizationmy-organization
organization.metadataOrganization metadata
{
  "attribute1": "value",
  "attribute2": "value",
  "attribute3": "value"
}
organization.branding.logo_urlURL of Organization logohttps://example.com/orglogo.png
organization.branding.colors.primaryPrimary branding color for Organization#000000
organization.branding.colors.page_backgroundBackground color for Organization’s login pages#FFFFFF

Current user information

You can only use the following variables for pages that render after authentication.
VariablesDescriptionExample
user.user_idID of the user profileauth0|XXXXXXXXXXXXXXXXXXXX
user.pictureURL of the user’s profile picturehttps://example.com/userimage
user.emailEmail address of useruser@example.com
user.email_verifiedBoolean of email verification status (true/false)true
user.app_metadataapp_metadata object of the user profile
{
  "attribute1": "value",
  "attribute2": "value",
  "attribute3": "value"
}
user.user_metadatauser_metadata object of the user profile
{
  "attribute1": "value",
  "attribute2": "value",
  "attribute3": "value"
}
user.family_nameFamily (last) name of userSmith
user.given_nameGiven (first) name of userAbigail
user.nameFull name of userAbigail Smith
user.nicknameNickname (alias) of userAbby
user.usernameInternal name of userasmith

Current screen information

VariablesDescriptionExample
dirIndicates the direction of the element’s text.auto, rtl, ltr
localeLocale used to render the page; matches one of the supported tenant languagesen-US
prompt.nameName of the currently rendered Universal Login promptmfa
prompt.screen.nameName of the currently rendered Universal Login screenmfa-login-options
prompt.screen.textsAll localized texts from the current screen
{
  "pageTitle": "Available methods"
}
stateRenders the current page’s state value, which is opaque and used for security purposes.

Prompts

The term prompt refers to a specific step of the login flow. A specific prompt may consist of one or more screens. You can manage prompts through the Auth0 Dashboard or the prompts endpoints of the Management API. The sections below provide details for each available prompt.

Custom query parameters

You can also use query parameters within the context by passing them to the /authorize endpoint when initiating the authentication request. These custom query parameters must have the ext- prefix. The following example uses the ext-ga and ext-test query parameters to the login page template:
<!DOCTYPE html>
<html>
  <head>
    {%- auth0:head -%}
  </head>
  <body>
    {%- auth0:widget -%}
  </body>
  <pre style='background: wheat'>
    <b>Value of the ext-ga parameter:</b>{{ transaction.params.ext-ga }}
    <b>Value of the ext-test parameter:</b>{{ transaction.params.ext-test }}
  </pre>
</html>
Custom query parameters have the following limitations:
  • Each ext- parameter name must be unique
  • One authorize request can can contain a maximum of ten ext- parameters
  • The ext- parameter name must start with ext-, contain only [a-zA-z0-9_-], and be a maximum of 28 characters, as in the following: /^ext-[\w-]{1,28}$/
  • The ext- parameter value must contain only [a-zA-Z0-9-.*~@+ /:_], and be a maximum of 255 characters, as in the following: /^[-\w.*~@+ /:]{1,255}$/

Custom signup prompts

If you use custom signup prompts, you must enable custom page templates. The following is the minimum template that allows custom signup prompts to render:
<!DOCTYPE html>
<html>
  <head>
    {%- auth0:head -%}
    <style>
      body._widget-auto-layout {
        --page-background-image: url('https://REPLACE/WITH/YOUR/BACKGROUND/IMAGE.png');
        background-color: var(--page-background-color);
        background-image: var(--page-background-image);
        background-position: center;
        background-size: cover;
        background-repeat: no-repeat;
      }
    </style>
    <title>{{ prompt.screen.texts.pageTitle }}</title>
  </head>
  <body class="_widget-auto-layout">
    {%- auth0:widget -%}
  </body>
</html>
To learn more, review Customize Signup and Login Prompts.

Examples

Login box + image layout

The following template will show the login box to the left, and an image to the right only for the login/signup pages. The rest of the pages will look like the default ones.
<!DOCTYPE html>
<html lang="{{locale}}">
  <head>
    {%- auth0:head -%}
    <style>
      body {
        background-image: url("https://images.unsplash.com/photo-1592450865877-e3a318ec3522?ixlib=rb-1.2.1&auto=format&fit=crop&w=2255&q=80");
        background-size: cover;
        background-position: center;
        background-repeat: no-repeat;
      }
      .prompt-wrapper {
        position: relative;
        display: flex;
        align-items: center;
        width: 480px;
        height: 100%;
        justify-content: center;
        background-color: rgb(60,60,60);
      }
    </style>
    <title>{{ prompt.screen.texts.pageTitle }}</title>

  </head>
  <body class="_widget-auto-layout">
    {% if prompt.name == "login" or prompt.name == "signup" %} 
        <div class="prompt-wrapper">
        {%- auth0:widget -%}
        </div>
    {% else %}
        {%- auth0:widget -%}
    {% endif %}
  </body>
</html>
Universal Login box with email username/password and image layout example

Page footers

The example below adds a gray footer with links to Privacy Policy and Terms of Services:
<!DOCTYPE html><html lang="{{locale}}">
  <head>
    {%- auth0:head -%}
    <style>
      body {
        background-image: radial-gradient(white, rgb(200, 200, 200));
      }
      .footer {
        background-color: rgb(120, 120, 120);
        position: absolute;
        bottom: 0;
        left: 0;
        padding: 16px 0; 
        width: 100%;
        color: white;
        /* Use a high z-index for future-proofing */
        z-index: 10;
      }
      .footer ul {
        text-align: center;
      }
      .footer ul li {
        display: inline-block;
        margin: 0 4px;
      }
      .footer ul li:not(:first-of-type) {
        margin-left: 0;
      }
      .footer ul li:not(:first-of-type)::before {
        content: '';
        display: inline-block;
        vertical-align: middle;
        width: 4px;
        height: 4px;
        margin-right: 4px;
        background-color: white;
        border-radius: 50%;
      }
      .footer a {
        color: white;
      }
    </style>
     <title>{{ prompt.screen.texts.pageTitle }}</title>
  </head>
  <body class="_widget-auto-layout">
    {%- auth0:widget -%}
    <footer class="footer">
      <ul>
        <li><a href="https://company.com/privacy">Privacy Policy</a></li>
        <li><a href="https://company.com/terms">Terms of Service</a></li>
      </ul>
    </footer>
  </body></html>
Universal Login box with email address/password and footers layout example

Page templates API

To set the page template, you need to use the . You first need to get a Management API token with the update:branding, read:branding, delete:branding scopes. If you are using the API Explorer Application to generate tokens, make sure those scopes are enabled for the Auth0 Management API. To set the template, you need to use the following endpoint:
curl --request PUT \
  --url 'https://{yourDomain}/api/v2/branding/templates/universal-login' \
  --header 'authorization: Bearer MGMT_API_ACCESS_TOKEN' \
  --header 'content-type: text/html' \
  --data '<!DOCTYPE html><html><head>{%- auth0:head -%}</head><body>{%- auth0:widget -%}</body></html>'
To retrieve the template, you need to use the following endpoint:
curl --request GET \
  --url 'https://{yourDomain}/api/v2/branding/templates/universal-login' \
  --header 'authorization: Bearer MGMT_API_ACCESS_TOKEN'
To delete the template, you need to use the following endpoint:
curl --request DELETE \
  --url 'https://{yourDomain}/api/v2/branding/templates/universal-login' \
  --header 'authorization: Bearer MGMT_API_ACCESS_TOKEN'
The maximum size for the Page Template is 100KB. If that is not big enough, consider moving images/css files outside of the Page Template code.

CSS customization

Page template limitations:
  • CSS class names change each time Auth0 builds the project. Custom CSS that targets these classes will break with each new build.
  • The HTML structure of Universal Login pages is subject to change. Avoid customizations that rely on the HTML structure to prevent any interruptions.
There are a few things that you can customize using CSS:
  • You can resize the login prompt by enclosing the variables below in <style> tags in the <head> element.
    • Use --prompt-width to adjust the container width. Its default value is 400px.
    • For Forms: Use --form-max-width to set the maximum form width. Its default value is 500px.
      • To apply your code to the Form page only, include {% if prompt.name == "custom-form" %} in the <head> element.
  • You can use a Google font by importing it and overriding the --font-family CSS variable.
  • You can hide the tenant logo by adding class="_hide-prompt-logo" in the <body> element.
  • You can specify a custom logo by adding class="_use-custom-prompt-logo" in the <body> element. This would let you, for example, change the login page logo depending on the application:
<!DOCTYPE html>
<html lang="{{locale}}">

  <head>
    <title>Welcome to {{ application.name }} </title>
    {%- auth0:head -%}
    <style>
      :root {
        --prompt-width: 800px;
      }
      {% if application.name == "Auth0 Community" %}
      #custom-prompt-logo {
      background-image: url('https://cdn.auth0.com/manhattan/versions/1.3312.0/assets/badge.png');
      }
      {% elsif application.name == "Auth0 Dashboard" %}
      #custom-prompt-logo {
      background-image: url('https://cdn.auth0.com/blog/auth0rta/theme/logos/auth0-logo-black.png');
      }
      {% endif %}
  </style>

  </head>

  <body class="_widget-auto-layout _use-custom-prompt-logo">
    {%- auth0:widget -%}
  </body>

</html>
The current implementation does not support further CSS customization. If you look at the HTML that is generated, you will see code like:
.c10d15918.c7b3b8672 {
  background: #D00E17;
}

Using the Auth0 CLI

You can use the Auth0 CLI to easily update Page Templates. In the Auth0 CLI, run: auth0 universal-login customize The Auth0 CLI will open two windows:
  • A browser window with a Storybook that shows the login page with the page template applied:
Page Templates Storybook
  • The default editor, with the page template code:
undefined
You can now change the page template code, and you will be able to preview the changes in your browser window. Once you close the window, you’ll be asked if you want to save the template. If you answer Yes, the template will be uploaded to your tenant.

Troubleshooting

If the template is not being applied, verify that you’re navigating to {customDomain}/authorize. If you’re navigating to {yourDomain}/authorize, Auth0 will not render the page template.