Building a Route Guard in React
In the last guide, we saw how we could show or hide links based on if a user was logged in or not, but we also saw how that doesn't actually hide the route itself, and so that would lead to a security vulnerability.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

So what we're gonna do now is walk through how we can hide the actual route definition, so, I'm gonna open up the app component, so if you open up Visual Studio Code, and go to app, under the componentDidMount(), I'm going to create a new method, so this new method is gonna be called authorizedPages().

You could also call it authorizedRoutes, it doesn't matter, you could call it whatever you'd like. And inside of here, I'm going to return an array, so I'm gonna return an array just like this, and the reason why I'm returning an array is because later on, I'll walk through how to have multiple pages that we only wanna show if a user is logged in.

So now that we have that, the only thing that we need to do is come down, and pull this route out, and then put it inside of the return statement. Now, for right now, we only have a single one, but eventually, we'll have a list of a couple there.

app.js

authorizedPages() {
  return [<Route path="/blog" component={Blog} />];
}

So, now that we have that, we are getting our authorized pages, you can test this out, just to confirm that it's working, so right under contact, right where it was, use curly braces and let's just say, this.authorizedPages() and hit save,

<Route path="/about-me" component={About} />
<Route path="/contact" component={Contact} />
{this.authorizedPages()}

and let's go take a look, and you can see that, if you hit refresh, we're still able to access the blog, so now, we're going to do exactly like what we did last time where we have a ternary operator right here. So inside of this curly bracket, give a little bit of room, I'm gonna say, this.state.loggedInStatus, if that is triple equal to LOGGED_IN, then I want to, with a question mark, I wanna show the authorized pages, hit save, or actually, it's gonna have a syntax error, so I don't hit save quite yet.

Come to right after this authorizedPages() and if nothing else is there, just type null, just like we did last time, and now Prettier will take care of our formatting, so what you can do is, you can see that no matter how many pages we put in authorizedPages(), each one of these is going to render out a route, and if we're logged in, it's gonna show up, and if we're not logged in, then these pages are not going to show.

<Route path="/about-me" component={About} />
<Route path="/contact" component={Contact} />
{this.state.loggedInStatus === "LOGGED_IN" ? (
  this.authorizedPages()
) : null}

So let's test this out in the browser and, if you hit refresh, now you can see we get the no match, so now, it says we couldn't find that page, even though that route used to be there and it's because it's no longer being rendered.

large

So, what we're doing, just to review, is we're creating a method. The method returns a list of routes, it's gonna put, if we had 10 in there, it would protect all 10. You can think of this almost like a route guard, it is going to ensure that if the user is not logged in, then the route is not even added to the codebase.

So that's what's really cool about this, is there's no way of hacking around this. If the user is not logged in, the route is not even there, it doesn't exist, so that is the right way to do it, so, from a security perspective, not only are we hiding the link. If someone were to get access to that link, we are also hiding the route itself, so you don't even have to worry about it and now you've caught both sides of the spectrum.

You've caught what the user is able to see, but also, what's in the codebase. So great job, we now have a full set of route guard code that will protect all of our pages that only you should be able to access.

Resources