How to add Auth0 authentication to React apps
No matter what kind of software you’re creating, ensuring security is a top priority in today’s application landscape. As more users access the web, safeguarding their information and maintaining your application’s reliability has become vital aspects of building a trustworthy web app.
Constructing authentication is more than just challenging in terms of implementation; it’s also a big security concern. To establish a strong and secure authentication process in your application, turning to a specialized authentication service provider like Auth0 can be incredibly effective.
In this tutorial, we’ll explore how to seamlessly integrate authentication into a React application using Auth0.
React and Auth0
React has gained immense popularity as a tool for creating lively and interactive user interfaces. In contrast, Auth0 stands as a robust platform for authentication and authorization. It equips developers with the means to smoothly establish secure authentication mechanisms.
Now, let’s look at some of the well-known features Auth0 brings to the table.
Auth0 Features
-
- User Authentication: Auth0 offers various authentication methods, including social logins (Google, Facebook, etc.), usernames and passwords, and more.
-
- Security: Auth0 handles security concerns like hashing passwords and managing tokens independently, doing all the heavy lifting for you.
-
- Customization: Auth0 provides ways to customize the authentication experience to match your application’s design. You can use their built-in templates to easily customize the UI of your authentication pages without coding. You can also get more fine-grained control over how your authentication page should look by writing your own CSS. Moreover, you can further customize the authentication flows as well.
Finally, using Auth0 in React is incredibly simple. Let’s explore that now.
Setting up the React app
To start, make sure you have Node.js and npm (Node Package Manager) installed. You can create a new React application using the Create React App (CRA) tool.
We’ll use the following command to create a new React app:
npx create-react-app auth0-react-app
cd auth0-react-app
Let’s also install the auth0-react-sdk:
npm install @auth0/auth0-react
Setting up Auth0
Let’s understand how we can set up Auth0 for your React application. We’ll do so using the following step
-
- Create an Auth0 Account
-
- Create a new Auth0 Application
-
- Get your application keys from the “Settings” tab
-
- Configure the callback URL to your local React application
You can also follow this video step by step to set Auth0 for your React application:
Integrating Auth0 into the React App
Now that we’re all set to integrate Auth0 in our React app, first, we’ll wrap our React app inside the <Auth0Provider/>
component in the src/index.js
file:
import React from 'react';
import { createRoot } from 'react-dom/client';
import { Auth0Provider } from '@auth0/auth0-react';
import App from './App';
const root = createRoot(document.getElementById('root'));
root.render(
,
);
This will let us use the useAuth0
hook throughout our app to access authentication-related functions and states. Make sure you use your own Auth0 application’s domain and client Id against the domain
and clientId
prop in the provider.
Login/Signup with Auth0
Let’s create a simple LoginButton
component that calls the loginWithRedirect
method on our Auth0 app. This button, when clicked, will call Auth0 to load its authentication page, which will handle the authentication for us.
import React from "react";
import { useAuth0 } from "@auth0/auth0-react";
const LoginButton = () => {
const { loginWithRedirect } = useAuth0();
return ;
};
export default LoginButton;
Let’s render this component inside our App.js file:
import './App.css';
import LoginButton from './LoginButton';
function App() {
return (
);
}
export default App;
Now if you click the Login button, you should land on the Auth0 authentication page where you can sign up or log in:
Showing User Profile Information
At the last step, if you simply go ahead and try to log in you’ll just be redirected back to the home page. We can actually get the logged-in user’s information using the useAuth0
hook. First, we’ll import this hook from the auth0-react
SDK. Then, we’ll get the user
object, isAuthenticated
, and isLoading
flags from the useAuth0
hook.
Based on the value of isAuthenticated
we can conditionally render the user’s profile information using the user
object or the <LoginButton/>
component:
import './App.css';
import LoginButton from './LoginButton';
import LogoutButton from './LogoutButton';
import { useAuth0 } from "@auth0/auth0-react";
function App() {
const { user, isAuthenticated, isLoading } = useAuth0();
if (isLoading) {
return Loading ...;
}
return (
isAuthenticated ? (
{user.name}
{user.email}
):
);
}
export default App;
If you now login again, you should see your profile information rendered on the page.
Logging out
Similar to log in, we can also create a simple <Logout/>
button component that calls the logout
method from the useAuth0
hook to logout the user:
import React from "react";
import { useAuth0 } from "@auth0/auth0-react";
const LogoutButton = () => {
const { logout } = useAuth0();
return (
);
};
export default LogoutButton;
However, a small setting you’ll need to configure for this is to add http://localhost:3000 as the logout URL which Auth0 will redirect to after logout:
We can then conditionally render the logout button:
import React from "react";
import { useAuth0 } from "@auth0/auth0-react";
import LogoutButton from "./LogoutButton";
import { useHistory } from "react-router-dom";
const Profile = () => {
const { user, isAuthenticated, isLoading } = useAuth0();
const history = useHistory()
if(!isAuthenticated) history.push('/')
if (isLoading) {
return Loading ...;
}
return (
isAuthenticated && (
{user.name}
{user.email}
)
);
};
export default Profile;
If you now click on the Logout button, you should no longer be logged in and your profile information will also disappear:
Creating Protected Routes
Currently, we only conditionally render the Login and Logout buttons along with the profile information. A regular web application will be much more complex than this and will have multiple routes that would render different pages and components.
We can easily use the withAuthenticationRequired
from the auth0-react
SDK to create a protected route for our application. Protected routes ensure that only authenticated users can access certain parts of your application. To create a protected route, you can use a higher-order component (HOC) or a custom hook
import { withAuthenticationRequired } from '@auth0/auth0-react';
const ProtectedRoute = ({ component, ...args }) => (
);
Now you can simply use this ProtectedRoute HOC for all your protected routes:
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import './App.css';
import LoginButton from './LoginButton';
import Profile from './Profile';
import ProtectedRoute from './ProtectedRoute';
function App() {
return (
);
}
export default App;
The route /profile
is a protected route and if a logged-out user tries to access it, Auth0 will automatically redirect them to the authentication page. Note that I’m using react-router-dom
v5 in the above example. I have also abstracted the profile information UI in a separate <Profile/>
component that I’m passing as the component
prop inside the <ProtectedRoute/>
component.
Redirect to Profile Page after Login
One last thing that we should do is automatically redirect users to the /profile
page after they log in. We can configure this in our React app by listening to the isAuthenticated
state from the useAuth0
hook. However, there’s a more simple way to do this. We can take advantage of the callback URL we set in our Auth0 application settings.
First, we’ll need to update the redirect_uri
in the Auth0Provider
as shown:
import React from 'react';
import { createRoot } from 'react-dom/client';
import { Auth0Provider } from '@auth0/auth0-react';
import App from './App';
const root = createRoot(document.getElementById('root'));
root.render(
"
}}
>
,
);
Then, we’ll need to update the same in the callback URL on our application settings page:
Now after login, you should be automatically redirected to the profile page.
Testing the Authentication Process
During development, it’s essential to test the authentication process thoroughly. One tool that can assist in this is Requestly. It allows you to modify API requests & responses and see how your app performs in various scenarios.
Download the Requestly desktop app and connect your Chrome window where your React app is running. After this, you should be able to see all the network requests between your React app and Auth0’s servers on Requestly. We’ll test two simple scenarios by modifying the response body of Auth0’s requests using Requestly.
When you log in, you’ll notice a request sent out to Auth0 to the endpoint https://dev-3vdnutm4bamutlcn.us.auth0.com/oauth/token
. This request actually gets the necessary authentication token that is used to fetch your profile information on the Profile page.
Let’s modify the response to this request by returning an empty authentication token. We’ll set the access_token
field in the API’s response as empty:
Now, let’s test the Login flow again:
As you can see, Auth0 neither allows us to get redirected to our own Profile page, nor fetches or displays any profile information. This means that the access_token
is essential for this flow, and its absence should break the flow for security purposes.
Now, let’s delete the rule so we can log in securely. This time, we’ll modify the response to the logout request.
I can simply search for a specific request I wish to find. In this case, I search for “logout” and return a 500, an erroneous status code in the request instead of the regular 302 it returns. Since this is a redirect request, we need to confirm two things. A status code 500 should now block the redirect but the logout should happen and we shouldn’t be able to access the profile page after that. Let’s test it now:
As you can see, we see the response of the logout request on the page now but the redirect doesn’t happen because of the 500 status code we set. However, logout does happen successfully nevertheless and an attempt to go to the profile page lands us back to the login page.
Conclusion
Adding authentication to a React application using Auth0 is a powerful way to enhance security and provide a smooth user experience. With Auth0’s features and the seamless integration into a React app, you can confidently build applications that protect user data while providing a great user experience.