Guard Client Side Routes Based on Auth State

Ryan Chenkie: [0:00] One of the most common needs in a single-page app as it pertains to authentication is to conditionally show certain elements of the UI. We've seen this already. We've got users going to the dashboard when they click login if they are already logged in or they go to the login page if they're not.

[0:17] Probably, one of the biggest needs aside from that is to redirect users away from routes that they should not be allowed to access. For example, I can go over to the dashboard here because I'm currently logged in. I've considered authenticated, because I've got a JSON Web Token that has not expired.

[0:35] If I were to log out, as it stands, I can still get the dashboard. Now, we can see that the authState here is causing this weird render, because I don't have a valid authState.

[0:46] As far as client-side routing goes, I shouldn't be able to get over to the dashboard in this case. This is important because even if your application is such that you are conditionally sending the user somewhere like the login screen if they're not authenticated.

[1:01] In terms of UI controls, you might be handling things correctly. A user who knows the application well can just come over and plug in a route directly in the URL bar. What we'll want to do is switch up our routing so that we guard against that. Come into appJS will want to be in the main appJS file for the application.

[1:22] Our job now is to create a custom route that is going to redirect users if they are not authenticated. This becomes pretty simple with React router because the route component takes a render prop which is going to be useful for doing that conditional routing.

[1:38] Essentially, what we'd want here is this Lambda that is going to check the user's AuthenticationStates and go to the desired route if a user is authenticated. Maybe, go to somewhere like the Home page if they're not. To do that work, we will first need authContext.

[1:54] Just like we do elsewhere, let's give ourselves a const authContext = useContext and we'll want our authContext. Now, in the render, we can just check authContext is authenticated.

[2:09] If that is true, let's send the user to their desired routes which is going to be the dashboard for this specific case. If not, let's redirect them. For that, we use the redirect component that comes from React router, so that auto-imported, for me, but just check to make sure that you have redirects coming in from React router DOM.

[2:30] If we need to redirect, we can just redirect to the home router, which is at slash. Once we close that up, we should be good to go, so we'll give that a save. This failed to compile because we've actually got braces here where we shouldn't have them. We just take out that semicolon to fix things up, and we should be good now.

[2:46] The user's current AuthenticationState is that they are not authenticated so let's try going to dashboard. If we do, we get redirected back to Home. If we log in, we should see that everything works correctly. Here we are at the dashboard, and we just once again plug that in directly.

[3:05] Now, we get the dashboard. Of course we don't want to rewrite this everywhere that we need it. We've got a lot of routes here that we want to apply it to. Instead, let's abstract this to its own component. For that, I'm just going to take this whole renderProp, and let's come up here and define a new components.

[3:24] We'll call this one authenticated route, and in authenticated routes we are going to de-structure out children. That's what we're going to eventually render, and then the props that may be passed in that we may not know about, anything that gets passed in, as a prop.

[3:40] Now, what we want to do is return a route, a regular route component from React router, but this time we are going to apply whatever props may have been passed in. Also the renderProp, and then we can close up that. We will need authContext and you can actually just lift it up into our new authenticated route component.

[4:02] Now we should be able to just apply authenticated route anywhere that we need it. We need it for dashboard. Because of the way this was set up previously and we still want to keep it how it was set up previously, where we include the actual route as a child. In this case, we want dashboard to be here.

[4:20] We've got to make a few changes, up here in our authenticated route component. Specifically instead of rendering dashboard, because this is dynamic, we want to render children. Because we are including app shell here -- app shell is just the sidebar and the navbar -- we can take that out of the render down here. Authenticated route should be applied to dashboard.

[4:42] We can test this if we log out and try to go to dashboard. We get kicked back to the Home page. Let's try the same thing with inventory and all of the other routes that needed as well. We're going to need it on inventory. Take the app shell. We're going to need it here on accounts, on settings, and on users.

[5:09] Give that a save to get everything formatted. We can try one of the others so maybe settings. Here, we are back at the Home page.