Protecting your React routes

If you've ever looked into your network tab when visiting a React app, chances are you've noticed that some apps send their entire bundle to their visitors. You might then wonder, how is that secure? Surely a motivated user could dive through React DevTools and find your protected routes?

First of all, you'd be correct - you won't stop a motivated user from seeing your admin panel UI, but that shouldn't worry us.

Secondly, it's your backend's job to worry about authentication and authorization before sending data to the frontend.

How it works

  • When users first load a React app, the user state is empty, meaning the user is unauthenticated
  • We protect routes in React by redirecting unauthenticated users to our login page (see React Router example)
  • When the user logs in, we send a request to our backend, and check if the credentials are valid (via database query, or passing off the entire exchange to a third-party service like Auth0 or AWS Cognito)
  • If the credentials are valid, the backend generates a token that's been signed with a secret we keep in the backend (so we know it's from our backend), and sends the token to the frontend
  • Back on the frontend, we keep the token in state so that we stop redirecting users to the login page
  • Now that the user can visit protected routes, we also use the token (normally using the Authorization header) in all API requests to our backend
  • Our backend checks if the token is signed correctly, as well as which user the token belongs to, and whether the user has permission before sending back any data
    • If the token is invalid, or not provided in the request, the backend sends back a response with a 401 Unauthorized HTTP status
    • If the token is valid, but the user doesn't have permission to view the data, the backend sends back a response with a 403 Forbidden HTTP status
    • We can then display a big ERROR page on our frontend if the API returns a 401 Unauthorized response, and none of our precious data gets send to unauthorized users
  • If everything is valid, we display our protected UI along with our data, and the user gets to use your app

Summary

In short, we shouldn't be worried about protecting our frontend from being downloaded. At worst, they'll find out what your admin/protected routes looks like, but won't get anything valuable.

It's the backend's role to ensure the user is both who they say they are, and that they are allowed to see the data.

(Shameless plug for the useEffect book I wrote below)

Tired of infinite re-renders when using useEffect?

A few years ago when I worked at Atlassian, a useEffect bug I wrote took down part of Jira for roughly one hour.

Knowing thousands of customers can't work because of a bug you wrote is a terrible feeling. To save others from making the same mistakes, I wrote a single resource that answers all of your questions about useEffect, after teaching it here on my blog for the last couple of years. It's packed with examples to get you confident writing and refactoring your useEffect code.

In a single afternoon, you'll learn how to fetch data with useEffect, how to use the dependency array, even how to prevent infinite re-renders with useCallback.

Master useEffect, in a single afternoon.

useEffect By Example's book cover