New Universal Login ToS acceptance

Problem statement

We want to add Terms of Service (ToS) acceptance links to their New Universal Login prompts in order to be able to adopt the NUL experience due to compliance requirements.

Solution

We’re announcing a supported way to do this in the short term for those customers who need this functionality now as a blocker for New UL adoption.
Now you can get around this using page templates.

https://auth0.com/docs/customize/universal-login-pages/universal-login-page-templates

We have made a change adding a supported custom field element that can be used for this use case. This is a simple approach and comes with limitations.

You can add a Terms of Service/Privacy Policy section to the sign-up prompt using Page Templates. To use Page Templates, review the following guidelines:

  • All signup prompts contain a HTML element of
    at the end of the primary form. You may safely use DOM manipulation techniques on this element.
  • You may target the signup prompt elements in order to interrupt form submission, e.g. if a user hasn’t consented to the Terms of Service.
    • The username/password form has an attribute of data-form-primary.
    • Each federated connection form has an attribute of data-form-secondary.
  • You may target the submit elements in order to disable or style them.
    • The primary button has an attribute of data-action-button-primary.
    • Federated connection buttons each have an attribute of data-action-button-secondary.

Limitations:

  • Since end-users could have JavaScript disabled, scripts inside of a Page Template are not guaranteed to run. Do not depend on Page Template scripts for critical functionality.
  • Localization is not built in and you must embed your own localization. See Add Terms of Service and Privacy Policy Links.
  • You must custom-style any content you add to the prompt.

Example 1: Add Terms of Service and Privacy Policy Links

This example adds links to the customer’s Terms of Service and Privacy Policy. It leverages Liquid template language to conditionally render different text based on the current language.

<!DOCTYPE html>
<html>

<head>
    {%- auth0:head -%}

    <style>
        #custom-field-1 {
            margin-top: 5px;
        }
    </style>
</head>

<body>
    {%- auth0:widget -%}
</body>

<script>
    {% if prompt.name === 'signup' %}
    var customField = document.querySelector('#custom-field-1');
    if (customField) {
        {% if locale == "es" %}
        customField.innerHTML = 'Estoy de acuerdo con los <a href="https://example.com/tos">Términos y condiciones</a> y nuestra <a href="https://example.com/privacy">Política de Privacidad</a>';
        {% else %}
        customField.innerHTML = 'I accept the <a href="https://example.com/tos">Terms and Conditions</a> and <a href="https://example.com/privacy">Privacy Policy</a>';
        {% endif %}
    }
    {% endif %}
</script>

    </html>

Example 2: Add Terms of Service and Privacy Policy Links Requiring Explicit Consent

This example adds links to the customer’s Terms of Service and Privacy Policy and adds a required checkbox that must be selected before the user is allowed to continue, accomplished by disabling form submission by default and enabling it only if the button is checked. If an end user doesn’t have JavaScript enabled in their browser, the form will submit normally, and the custom links will not be shown.

<!DOCTYPE html>
<html>

<head>
    {%- auth0:head -%}

    <style>
        [data-action-button-primary]:disabled,
        [data-action-button-secondary]:disabled {
            background-color: #ccc;
            color: #444;
            pointer-events: none;
        }
    </style>
</head>

<body>
    {%- auth0:widget -%}
</body>

<script>
    {% if prompt.name === 'signup' %}
    function disableFormSubmitHandler(e) {
        e.preventDefault();
    }

    function disableSubmit() {
        document.querySelector('[data-form-primary]').addEventListener('submit', disableFormSubmitHandler)
        var secondaryForm = document.querySelector('[data-form-secondary]');
        if (secondaryForm) {
            secondaryForm.addEventListener('submit', disableFormSubmitHandler)
        }
        document.querySelector('[data-action-button-primary]').disabled = true;
        var secondaryButtonNodeList = document.querySelectorAll('[data-action-button-secondary]');
        for (var i = 0; i < secondaryButtonNodeList.length; i++) {
            secondaryButtonNodeList[i].disabled = true;
        }
    }

    function enableSubmit() {
        document.querySelector('[data-form-primary]').removeEventListener('submit', disableFormSubmitHandler)
        var secondaryForm = document.querySelector('[data-form-secondary]');
        if (secondaryForm) {
            secondaryForm.removeEventListener('submit', disableFormSubmitHandler)
        } document.querySelector('[data-action-button-primary]').disabled = false;
        var secondaryButtonNodeList = document.querySelectorAll('[data-action-button-secondary]');
        for (var i = 0; i < secondaryButtonNodeList.length; i++) {
            secondaryButtonNodeList[i].disabled = false;
        }
    }

    var customField = document.querySelector('#custom-field-1');
    if (customField) {
        disableSubmit();
        var customContent = "\n    <input id=\"terms-and-policies\" name=\"terms-and-policies\" type=\"checkbox\" required>\n    <label for=\"terms-and-policies\">\n        I accept the <a href=\"https://example.com/tos\">Terms and Conditions</a> and <a href=\"https://example.com/privacy\">Privacy Policy</a>\n    </label>";
        customField.innerHTML = customContent;
        var checkbox = customField.querySelector('input[name="terms-and-policies"]')
        checkbox.addEventListener('change', function(e) { e.currentTarget.checked ? enableSubmit() : disableSubmit() });
    }
    {% endif %}
</script>

</html>