Select image in MFA Page (Universal Login - New) based on Application/ClientId

Hi,

The page Dashboard > Universal Login > Multi-factor Authentication allows you to customize the HTML of the MFA Page.

In a setup where there are different Applications defined (Single Page Apps), I wonder if it is possible to differentiate the logo in this screen, based on the client Id of the application the user is trying to login to?

image

I read a lot about customization in the Auth0 docs (starting here Customize the HTML for the MFA page) but I think I’m overlooking something.

I was thinking of doing something like this:

return new Auth0MFAWidget({
    container: "container",

    theme: {
        {% if client.id === '[clientid of first application]' %}
        icon: "https://url-to-image-for-application-1",
        {% elsif client.id === '[clientid of second application]' %}
        icon: "https://url-to-image-for-application-2",
        {% else %}
        icon: "{{ iconUrl | default: '//cdn.auth0.com/styleguide/1.0.0/img/badge.png' }}",
        {% endif %}
      primaryColor: "{{ primaryColor | default: '#ea5323' }}"
    },

Kind regards,

Emiel

Hey there!

Unfortunately as far as I remember there is no straightforward way from our docs to do that, but I will try to look through the forum for some workaround as there were a couple of users trying to achieve this.

Hi Emiel,

I have also searched for this for a long time, recently I have figured out how to do this.

Personally I think this is a great solution because you will continue to use the Auth0MFAWidget

  (function() {
  
  const parseJwt = (token) => {
  	try {
    	return JSON.parse(atob(token.split('.')[1]));
    } catch (e) {
    	return null;
    }
  };
  
  const decodedToken = parseJwt("{{ requestToken }}");

  const isYourClient = decodedToken && decodedToken.clientId === 'YOUR_CLIENT_ID';
 
  const theme = isYourClient
	? {
  	  icon: 'url-to-your-custom-logo',
      primaryColor: '#255a57'
    }
	: {
      icon: "{{ iconUrl | default: '//cdn.auth0.com/styleguide/1.0.0/img/badge.png' }}",
      primaryColor: "{{ primaryColor | default: '#ea5323' }}"
    };

  const tenantFriendlyName = isYourClient 
  	? 'Your Client Name'
  	: "{{ userData.tenantFriendlyName }}";

  var css = '.auth0-lock.auth0-lock .auth0-global-message.auth0-global-message-success,.auth0-lock.auth0-lock .auth0-global-message.auth0-global-message-error{ background: #255a57 !important; }';
  var head = document.head || document.getElementsByTagName('head')[0];
  var style = document.createElement('style');
		
  if(isYourClient ){
    head.appendChild(style);
    style.type = 'text/css';
    
    if (style.styleSheet){
      // This is required for IE8 and below.
      style.styleSheet.cssText = css;
    } else {
      style.appendChild(document.createTextNode(css));
    }
  }
  
  return new Auth0MFAWidget({
    container: "container",
    theme,
    requesterErrors: [
      {% for error in errors %}
        { message: "{{ error.message }}", errorCode: "{{ error.code }}" }
      {% endfor %}
    ],

    mfaServerUrl: "{{ mfaServerUrl }}",
    {% if ticket %}
    ticket: "{{ ticket }}",
    {% else %}
    requestToken: "{{ requestToken }}",
    {% endif %}
    postActionURL: "{{ postActionURL }}",

    userData: {
      userId: "{{ userData.userId }}",
      email: "{{ userData.email }}",
      friendlyUserId: "{{ userData.friendlyUserId }}",
      tenant: "{{ userData.tenant }}",
      {% if userData.tenantFriendlyName %}
      tenantFriendlyName
      {% endif %}
    },
    globalTrackingId: "{{ globalTrackingId }}",
    {% if allowRememberBrowser %}allowRememberBrowser: {{ allowRememberBrowser }}, {% endif %}
    {% if stateCheckingMechanism %}stateCheckingMechanism: "{{ stateCheckingMechanism }}", {% endif %}
  });
})();

I hope it is of some use for you!

1 Like

This is a very cool solution @v.ottens! Thanks!
This will actually work for me! :slight_smile:

Maybe @konrad.sopala can comment on this solution as well?

Hi @konrad.sopala ,

Have you managed to find any work around solution for this?
We have two applications in our tenant and we want to customize the UI based on the application or clientID, but I can’t seen to access the clientID variable from inside the Multi Factor template.

Could you provide a way to do this? The above solution unfortunately does not work as we have a ticket instead of a {{requestToken}}.

Thanks,
Claudine

Hello Claudine,

This solution works for the customized MFA page when using the Universal Login.

A small excerpt from @v.ottens answer:

    <!-- ... Omitted for brevity -->
  </div>
</div>

<script src="//cdn.auth0.com/js/mfa-widget/mfa-widget-1.7.min.js"></script>

<script>
      
  (function() {
    
    const parseJwt = (token) => {
        try {
          return JSON.parse(atob(token.split('.')[1]));
      } catch (e) {
          return null;
      }
    };

    const decodedToken = parseJwt("{{ requestToken }}");

    if (decodedToken.clientId === '[the client id or your application]') {
        // do something specific to that application.
    }

    ... rest of script tag contents removed for brevity...

The clientId is ‘scrambled’ somewhere in the request token ({{requestToken}}) that you see in the URL.
You don’t need to read it from the URL, you get it injected in the MFA script ("…the property requestToken will be available.").

This requestToken is a Base64 encoded string. The parseJwt function calls atob to decode that and after that use JSON.parse to - you guessed it - parse the string into Json.
Now you can read the property clientId from it.

Good luck!

Emiel

Many thanks for your detailed response Emiel!

The issue I’m having when I try the above, is that it returns null. There is no {{requestToken}} property available. We have a ticket property instead which is visibile in the url when a user is invited to enroll in MFA from a link in email.

Unfortunately, decoding the ticket property doesn’t seem to work with the above solution.

Thanks,
Claudine

Hi Claudine,

Sorry… I missed your statement:

Do you perhaps use Auth0’s post_ticket API described in Create Custom Enrollment Tickets.

We’re not using this mechanism when creating users. I have no idea how to get client Id from that ticket. The docs seem a bit scarce on that.

Emiel