Hi! We have a React SPA with a Node backend and want to integrate it with Auth0. As a starter we want to use Auth0 DB authentication via user/pass but in the future the plan is to add support for social login. On the app side the integration journey so far has been:
authorize() from the
auth0-js library (either with redirect or pop-up). This works ok, but then we would like to customize the UI.
One way to do this is dashboard, Universal Login → Settings. Here we can tweak the logo, primary and background color, which is nice, but we want more control over the style.
Go to Universal Login → Log-in template. This seems to be using the Lock component, so doing some research around that I got to Customize Classic Universal Login Pages where it says “Auth0.js is the SDK used for interacting with the Auth0 authentication API. Primarily, you would use the SDK if you need to build your own custom login UI…”.
At a first glance using the JS SDK with custom domains seems to be what I’m looking for, as that would allow us to get the most seamless signup / login experience.
However, when going to the Auth0 js SDK page (Auth0.js v9 Reference) it mentions that it is an embedded login method, which per Centralized Universal Login vs. Embedded Login is not recommended.
This brings to me a couple of questions:
Is there a way to fully customize the signup / login pages (html+css) using Universal Login? Or to do that the only way to go is to use our own forms with the auth0-js lib?
In Centralized Universal Login vs. Embedded Login the main issue seems to be the risks associated with cross-origin authentication. However, if we use custom domains to match the one of our app, that shouldn’t be an issue (and Cross-Origin Authentication seems to corroborate that). So, is a custom form with auth0-js lib + custom domains any less secure than using the universal login? If so, can you explain why?
Thanks in advance,
For the first point, you can fully customize the HTML and CSS with the classic experience of Universal Login; in order to perform a full customization you’ll need to use something other than Lock given Lock already provides a fixed user interface.
That something other is indeed Auth0.js library and you’ll find a universal login template that uses it (as mentioned at https://auth0.com/docs/universal-login/advanced-customization#choose-a-template-to-begin).
It seems the source of the confusion is that both Lock and Auth0.js web libraries can be used to implement embedded login as well as the classic experience of universal login. In conclusion, you may need to ignore some of the warning in the reference documentation as they may not apply for your usage of the libraries.
For the second point, you’re correct that if you use custom domains and have all applications under the same parent domain then the most common issues associated with embedded authentication do not apply. However, you are still left with an approach that forces every single application to handle user credentials so the general recommendation would always be to use universal login (even if a fully customized interface is required).
Thanks for the quick reply João! Indeed, the confusion came from using Lock or Auth0.js as part of the universal login template, which I assumed would turn them into an embedded login. Thanks for clarifying that.
For the second part, I think I understand your point, but for the case of a single app, does it make any difference? The main point I see here in favor of an embedded login is the ability to keep it together with the rest of our app in our source control and reuse our CSS, whereas in the case of customizing the login we need to keep these templates in the Auth0 side and prepare a set of assets to be consumed by it. Definitely something worth doing if there is a security risk, I just want to understand if such a risk exists.
I agree with you that the universal login approach may impose some overhead in terms of then having to manage the login page interface separately, but even with just a single application it has some benefits. I’m not saying that you can’t implement embedded login in a secure way, but the problem with embedded is that your own application will still have to handle user credentials and just that by itself is a huge thing.
For example, lets suppose the application suffers from an XSS vulnerability; the impact of that would be bad in either cases, however, it could be argued that the possibility of exposing an end-user password is always greater than exposing tokens and if you implement embedded login then a vulnerability could lead to actual password being exposed.
In conclusion, I would personally prefer the overhead of managing a separate deployment pipeline so that the login user interface is integrated through universal login instead of having to handle user credentials (passwords) in my client applications.
Makes sense, thanks for the detailed answer!