Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
January 26, 2021 02:02 pm GMT

Truly Protected React Routes

Are you in doubt that your React routes are really protected ? There are lots of tutorials out there that talk about secured routes, protected routes, private routes or restricted routes. Its pretty misleading because even though you have protected routes, it is possible to get past your login page and get access to all the code in your protected routes.

Perhaps people are telling you that it isnt worth going for server side rendering (SSR) in order to truly protect the graphic content of your website. Maybe theyre saying that securing the backend should be enough because that will prevent you from displaying any sensitive data to fake-logged-in users. But WHAT IF you still want more security and you want to block all access? After all, you dont want your competitors to hack into your admin dashboard, to see how youre progressing or stealing your ideas.

This article will answer the following questions

What's not secure about protecting routes in the client?

In React there is nothing such as truly private routes as it's a single page application (SPA) which means that all the code is served to the browser.

This is typically how we protect routes in the browser:

{isLoggedIn ? <PrivateRoutes> : <PublicRoutes/>}
Enter fullscreen mode Exit fullscreen mode

With this code here above, you can't guarantee that the user won't tweak your javascript, change isLoggedIn to value true and pretend to be an authenticated user.

Let's see how we can get access to ALL the code of your application. Here's a sandbox example where I've made a typical login system with protected routes. Notice that I lazy loaded two components: "PrivatePage" and the "LoginPage". Then I used the "classic" way of importing "AnotherPrivatePage" even though that component is not being used (this is on purpose).

import React, { useState, Suspense } from "react"import AnotherPrivatePage from "./AnotherPrivatePage"const PrivatePage = React.lazy(() => import("./PrivatePage"))const LoginPage = React.lazy(() => import("./LoginPage"))export default function App() {  const [isAuthenticated, setAuthenticated] = useState(false)  return (    <Suspense fallback={<div>Loading .. </div>}>      {isAuthenticated ? <PrivatePage /> : <LoginPage />}    </Suspense>  )}
Enter fullscreen mode Exit fullscreen mode

You can either follow the article or test yourself by opening up the sandbox example, and opening page in new window by clicking on the two squares in the upper right corner (the icon can vary between browsers):

codesandbox

Go to devtools by right clicking, choose "Inspect" (if you're in Chrome). Then go to "Sources".

source_chrome

Here above you can see that we have two components loaded to the browser, "LoginPage" because isAuthenticated = false. We also have "AnotherPrivatePage" because if you don't lazy load, we can very easily access that component as well. The "hacker" doesn't even have to hack to look around and read the code and maybe see some static data.

It needs a bit more effort to get hold of the other component "PrivatePage.js" as it's lazy loaded. There are lots of ways to do that, but here's one:
Install React dev tools if you don't have it already, go to Components:

devtools1

Then click on "App" and change hook's state to true:

devtools2

And you'll see how we get access to the "PrivatePage", the last component we didn't have loaded in of our application and was supposed to be protected. There are of course lots of other ways to hack React. To increase security you could for example disable access to devtools in production but there's most often some other way to get around things.

But why do we then protect our routes in the front end?

You can protect your components/graphics on a:

  • component level

  • route level

Either way, the main reason for why we're protecting those graphics is just to make the user experience nicer. The reason why we do it on a route level is just to make our code more organized by avoiding duplications.

How are protected routes nicer for the user ? Imagine, the user has already visited our page. Next time he visits, he'll tap the url of your website and his browser autocompletes the website url without adding /login to the end of the URL. He goes straight to http://www.somewebsite.com, but he's not authenticated anymore (let's say that he logged out the last time or his authorization token has expired). And because he's not logged in anymore the user will see the page without any content and no possibility to interact with anything that has to do with server data. It would be nicer for the user to have no direct access to the private pages and instead automatically land on the login page.

But is it so important to have truly protected routes?

In the worst case scenario, the user can hack its way with javscript to your private routes and will see some empty tables, graphs, or messages that tell you that there is no data etc. And without content, your website will look like nothing, might even be ugly or at least it will be unusable. Well that's not so serious, we could even say that our hacker deserves that! . But you have to make sure that there is no possibility for the hacker to access sensitive data You should not leave any sensitive static data in your client and ensure that all your API endpoints are secure and make the server throw 401 if the user is not really authenticated and authorized.

But is that really enough? Like I said above you might have built an admin dashboard for your company. Even without access to sensitive data, your competitor could possibly deduce where your company is heading by reading any static texts in your app, or by trying to make sense of your graphics, even though they're missing the content. Apart from that, truly securing the private part of your app adds an extra layer of security to your app, which can only be positive.

gandalf

How to make truly secured routes?

There are several ways to achieve this. You could use SSR to solve this problem or you could stay with 100% SPA and serve your application in two parts. I've an example of the how to achieve the latter solution. There are lots of ways to do this and here I have an example of this using Express server in Node.js that serves two different SPAs, one containing the login page and the other containing the app itself. You can see this project here on github.

If you clone that project and run it, you should be aware that it takes pretty much time. Instead you can also just follow the article and check out the code.

If you run the project and go to devtools, you'll see in "sources" that you only have the login page loaded to the browser.

unauthenticated

Here there's no possibility to access the authenticated part of the application because it won't be served to the browser unless you provide the correct auth inputs in username and password thanks to this code in server.js

app.get("/protected", (req, res) => {  if (req.signedCookies.name === "admin") {    app.use(express.static(path.join(__dirname, `/${privatePage}/build`)))    res.sendFile(path.join(__dirname, `/${privatePage}/build/index.html`))  }})
Enter fullscreen mode Exit fullscreen mode

You can try to log in, username: admin and password: 123...

and voil:

authenticated

Here we're logged in and now we have the authenticated part of the application loaded in the browser and as a side effect, the login page is no more loaded in the browser.

I hope this article has been useful for boosting the security of some of your websites that might use some extra layer of restriction! If you found this article helpful, don't hesitate to leave a comment or share it with others. Same of course if you have something that you would like to point out :)


Original Link: https://dev.to/daggala/truly-protected-react-routes-b8a

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To