Using React to Customize Your Auth0 User Experience
Use this guide and supporting example code to see how we scaled our Auth0 implementation by leveraging React.
As our implementation with Auth0’s branding and styling grew more complex, our engineering team looked for a solution to simplify our implementation and accelerate our development. Our goal was to leverage existing tools and frameworks we were already using. As a result, we leveraged React for our Auth0 Universal Login pages.
In this blog, we’ll take a look at how we implemented React with Auth0’s Universal Login, but check out our repo with a working code example to learn more.
Challenges while Scaling Universal Login
This solution presented our team with some challenges as we began to scale:
- Context Switching - All of our other frontend applications were written in React, so our team members had to context switch when working with Universal Login.
- Redo Theme - Our team had implemented custom styling with Material UI components, forcing us to re-implement all of our custom stylings.
- Hard to Test - We no longer could use React Testing Library and Cypress for unit and acceptance testing. This created a slow feedback loop to verify sign-up and sign-in behavior until we deployed the latest changes.
Due to these challenges with Universal Login, our engineers avoided working on the changes. This was problematic, so we looked for a solution.
How to manage Auth0 Universal Login with React
Since our team was already using React for all of our existing applications, we decided to leverage React to manage our Universal Login experience. To do this, you will need to perform the following four steps:
- Create your form components
- Add Auth0 Context Provider
- Add module to login.html
- Build the static page
Let’s jump in.
1. Create your form components
With React, we can break up the HTML in the Universal Login page into three components: 1) Sign-up, 2) Sign-in, and 3) Reset password. We benefit from using out-of-the-box components, such as Material UI’s TextField component:
In this example, we can set things, such as onChange events, set value from state, and set styling on our component.
2. Add Auth0 Context Provider
This step adds most of the magic to the solution.
We need a way to manage state within our React application. The default Universal Login template injects and configures an instance of the `WebAuth` client. We need to replicate this behavior.
First, we need to import the <span class="code">auth0-js</span> dependency to give us access to <span class="code">WebAuth</span> and a way to initialize the WebAuth client:
This code is copied directly from the default Universal Login template. Auth0 will automatically inject the <span class="code">auth0Config</span> property into the page when it loads, giving us access to client, tenant, and callback settings.
Next, we need to add a context that will hold the state of our Universal Login application:
This will hold the state of our application including ability to login, social login, password reset, and sign-up. We also are adding a custom <span class="code">Mode</span> state to toggle between the different views of our application.
Now we need to create our <span class="code">WebAuthProvider</span> and initialize the Auth0 WebAuth instance:
Notice this is calling <span class="code">createAuthClient</span> which will initialize the <span class="code">WebAuth</span> client from the injected Auth0 settings.
Here is login for reference:
Finally, we need to export our context:
With our WebAuthProvider complete, we just need to wrap our App with it to make the state available to all of our components:
At this point, we can change the mode and call all methods on the WebAuth client from any of our form components. You can see the completed WebAuthProvide here.
3. Add module to login.html
3. Build the static page
With the React application done, we need to build and deliver it to Auth0. To do this, we utilize Parcel and build it with the command:
This will compile our application.The resulting <span class="code">login.html</span> will hold a single file containing our compiled React application.
To deploy the application, it is highly recommended you look at Auth0’s deployment CLI. We can copy the resulting <span class="code">login.html</span> file to <span class="code">pages</span> directory and easily deploy it to our Auth0 tenant:
Replacing the default Universal Login template with React gives our team numerous benefits:
- Reduces context switching - Our team can now work exclusively with React
- Breaks up the monolith form - We separated our application into individual components
- Faster page load times - Since our page was compiled, we reduced the payload size
- Faster feedback loop - Our engineering team gained the benefits of testing and hot reloading
- Reuse components and styles - We could copy components and our company theme over with minimal changes
More importantly, our team now no longer avoids working with the Universal Login forms. We gain all of the efficiencies of reusing our existing tools, frameworks, and workflows to build and deliver our login experience.