Fork me 🍴

Willian Antunes

Email and Universal Login Templates with Liquid on Auth0

7 minute read

auth0, liquid, ruby, sinatra

Table of contents
  1. How it works
  2. Email templates available
    1. Verification Email (using Link)
    2. Verification Email (using Code)
    3. Welcome Email
    4. Enroll in Multifactor Authentication
    5. Change Password
    6. Blocked Account Email
    7. Password Breach Alert
    8. Verification Code for Email MFA
    9. User Invitation
    10. Passwordless Email
  3. New Universal Login templates available
    1. Basic
    2. Login box + image
    3. Page footers
    4. Terms of use acceptance
  4. Conclusion

One thing that annoys me is how complex a software development life cycle can be if you're coding a project that depends on the platform to test and run in some sense. You can see similar circumstances if you're building something that relies on a Liquid template engine and Auth0. It has great guides about Customize Email Templates and Customize New Universal Login Pages, but they're insufficient. That's why I'm sharing the project Auth0 Liquid Tester so you can save time when creating your custom template 🚀.

How it works

You can issue the following command:

docker-compose up

Then you can check all the templates at http://localhost:9292/. Because of this volume, if you update any template in the views folder, it will reflect immediately after a refresh in the browser. You can also test more complicated scenarios by changing what Liquid receives through the controllers:

All email templates come with some configuration about i18n. Look at this example from welcome_email.liquid:

{% assign language = user.user_metadata.preferredLanguage %}
{% if language %}
  {% assign language = user.user_metadata.preferredLanguage | slice: 0,2 %}
{% endif%}
{% assign company_name = "Rave of Phonetics" %}
{% capture company_image %}
  <img alt="Rave of Phonetics" height="auto" src="https://avatars.githubusercontent.com/u/83559025?s=200&v=4" style="border: 0; display: block; outline: none; text-decoration: none; height: auto; width: 100%; font-size: 13px" width="150" />
{% endcapture %}
{% if language == 'pt' %}
  {% capture action_image %}
    <img alt="Símbolo que representa verificação" height="auto" src="http://cdn.auth0.com/website/emails/product/top-verify.png" style="border: 0; display: block; outline: none; text-decoration: none; height: auto; width: 100%; font-size: 13px" width="80" />
  {% endcapture %}
  {% capture highlighted_title %}
    Cadastro validado.<br /> Seja bem-vindo!
  {% endcapture %}
  {% capture bottom_text %}
    Você recebeu este e-mail porque você tem uma conta no {{ company_name }}. Se você não sabe o porquê está recebendo esta mensagem, por favor entre em <a href="{{ support_url }}" style="color: #0a84ae; text-decoration: none">contato conosco</a>.
  {% endcapture %}
{% else %}
  {% capture action_image %}
    <img alt="Symbol that represents verify" height="auto" src="http://cdn.auth0.com/website/emails/product/top-verify.png" style="border: 0; display: block; outline: none; text-decoration: none; height: auto; width: 100%; font-size: 13px" width="80" />
  {% endcapture %}
  {% capture highlighted_title %}
    Your account has been verified.<br /> Seja bem-vindo!
  {% endcapture %}
  {% assign highlighted_title = "You have been verified. Welcome!" %}
  {% capture bottom_text %}
    You’re receiving this email because you have an account in {{ company_name }}. If you are not sure why you’re receiving this, please contact us through our <a href="{{ support_url }}" style="color: #0a84ae; text-decoration: none">Support Center</a>.
  {% endcapture %}
{% endif %}

The project also includes basic tests. In theory, you can create a test for each email template to guarantee that Liquid can render it correctly, including any required param that must be present, like {{ code }} or {{ url }}. Check out this sample where we assert that the verification email is rendered properly:

RSpec.describe(EmailController) do
  context "verification email link" do
    it 'should render properly' do
      get '/verification-email-link'

      expected_values = [
        "jafar@willianantunes.com",
        "https://www.willianantunes.com/",
        "https://github.com/willianantunes/tutorials"
      ]

      expect(last_response.status).to(be(200))

      expected_values.each do |name|
        expect(last_response.body).to(include(name))
      end
    end
  end
end  

Email templates available

Here's a list of what is available and a brief description of each one followed by its image. I took the definitions from Auth0 😁.

This email will be sent whenever a user signs up or logs in for the first time.

It's a template email about the process of verifying the email using a link.

Verification Email (using Code)

This email will be sent in scenarios where the user needs to prove they have access to the email on file for an account:

  1. You have enabled the code-based email verification flow, and a user signs up or logs into the account for the first time.
  2. You have enabled the Adaptive MFA policy, and there is a low-confidence transaction for which account ownership must be verified.

It's a template email about the process of verifying the email using a code. This code is provided in the application.

Welcome Email

This email will be sent once the user verifies their email address. If the Verification Email is turned off, it will be sent when the user signs up or logs in for the first time.

It's a template email about a welcome message after the user's verification.

Enroll in Multifactor Authentication

This email will be sent when an admin sends a guardian enrollment email.

The template email has a link where the user goes to a site to enroll in multi-factor authentication.

Change Password

This email will be sent whenever a user requests a password change. The password will not be changed until the user follows the verification link in the email.

The template email has a link where the user configures his new password.

Blocked Account Email

This email will be sent whenever a user is blocked due to suspicious login attempts.

The template email informs the user that the identity provider has detected suspicious activity in his account. Then, the user can unblock his account by clicking on a button.

Password Breach Alert

This email will be sent whenever Auth0 detects that the user is trying to access the application using a password that a third party has leaked.

The template email informs the user that his account has been compromised. He won't be able to log in again until he changes his password.

Verification Code for Email MFA

Will provide the MFA verification code to a user using an MFA email verifier.

The template email informs a code that the user can use to complete an MFA step.

User Invitation

This email will be sent whenever a user is invited to an organization or application.

The template email has an invitation link, including other details, where the user is authorized to join the organization.

Passwordless Email

Will provide a code that the user can use to log in.

The template email provides a code that the user can use to authenticate himself. This is known as a one-time password.

New Universal Login templates available

Again I took the templates from Auth0, excluding the one with a modal for terms of use. You can implement the terms of use with Redirect with Actions, but it's a lot more complicated as it requires an external service. All explained, let's see the templates.

Basic

The most straightforward template. It shows what happens if you just use the widget without anything else.

It shows a login box on the upper left of the page. It has nothing apart from that.

Login box + image

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. Use the query string to change how it behaves.

There are two panels: One panel has the login box, and the other has an image.

Page footers

The template adds a gray footer with links to Privacy Policy and Terms of Services.

The login box is centered on the screen. You also have the footer informing the terms of use and the privacy policy.

Terms of use acceptance

This would happen only during the sign-up flow. The user would have to accept before going on.

It has a modal informing the user about the terms of use and the privacy policy. To proceed, the user must accept the terms.

Conclusion

At first glance, Auth0 seems to have all the sample projects you need to create yours, but that's only partly correct. Most sample projects are not production-ready, which is understandable from a certain point of view. Nevertheless, Auth0 offers a great development experience, and I can assure you it's on a whole different level when you compare it with its competitors. Excellent docs, various sample projects, great articles, easy integration process, diversity of libraries and SDKs, and many more. However, it's not flawless, and that's totally fine 🙂.

See everything we did here on GitHub.

Posted listening to Made of Tears, Joe Satriani 🎶.


Have you found any mistakes 👀? Feel free to submit a PR editing this blog entry 😄.