In today's article, I will show you how you can set up an automatic redirect to a secured/restricted page in your react application after the user is authenticated.
INTRODUCTION
Let's assume that in your app, you have a page that needs authentication before a user will be able to access it, for example, the dashboard. This means that before a user is allowed to access the dashboard, he must be logged in.
Now, What if for any reason (session timeout, expired cookie, etc.), the user logs out of the app, but needs to revisit that same page on the dashboard? Or maybe he tries to visit information on the dashboard by clicking on the link from an email sent to him? How would you redirect this user back to the link he tried to visit after authentication?
This question will immediately make you understand that it is not enough to ask a user to log in before he can access a restricted page. But you should also redirect the user to the restricted page immediately after he is authenticated.
STILL CONFUSED? LET ME EXPLAIN BETTER
So I have this page http://my-website.com/dashboard/update-profile
that needs the user to be authenticated before he is allowed to visit it. Whenever a user that is not authenticated tries to visit it, he will be redirected to http://my-website.com/login
Now the goal is to preserve this URL http://my-website.com/dashboard/update-profile
so that when the user is authenticated successfully, he will be redirected back to it.
I will show you how you can achieve this in your React App, and if you should understand the logic, you can implement it anywhere!
USING A QUERY PARAMETER
In this approach, I will check if the user is not logged in, then retrieve the URL he is trying to visit, store it in the query parameter next
, and then redirect him to the login page. If authentication is successful, I will redirect him back to the URL in the next
query parameter.
Place this code on a secured/restricted page (a page that requires authentication)
To achieve this, the first thing that I need to do is to check if the user is not logged in.
useEffect(() => {
isAuthenticated().then(res => {
//check if user is not logged in
if(!res){
//----
}
}
}, []) //make the function run only once when the component mounts
Now we need to create a new URL object with the link that this user will be redirected to in order to get authenticated.
In my case, it will be the /login
page and the reason why I am creating a new URL object with it is that I am going to manipulate the link by adding a query parameter later on.
useEffect(() => {
isAuthenticated().then(res => {
//check if user is not logged in
if(!res){
//create a URL object with the Login Link
const loginUrl = new URL('http://my-website.com/login');
}
}
}, []) //make the function run only once when the component mounts
Now before we continue, we need to make sure that the user is trying to visit a restricted page in the dashboard. We can do that by checking if the current URL contains /dashboard
.
I will use a regular expression inside the match
method to perform this search on the current URL.
useEffect(() => {
isAuthenticated().then(res => {
//check if user is not logged in
if(!res){
//create a URL object with the Login Link
const loginUrl = new URL('http://my-website.com/login');
//check if user is trying to access dashboard without logging in
if(window.location.href.match(new RegExp('/dashboard', 'i'))){
//---
}
}
}
}, []) //make the function run only once when the component mounts
Now we need to append the link the user tried to visit as a query parameter to the URL object we created earlier, and then redirect the user to the full URL from this URL object.
useEffect(() => {
isAuthenticated().then(res => {
//check if user is not logged in
if(!res){
//create a URL object with the Login Link
const loginUrl = new URL('http://my-website.com/login');
//check if user is trying to access dashboard without logging in
if(window.location.href.match(new RegExp('/dashboard', 'i'))){
//Get the url he wanted to visit
const next = window.location.href
//append it to the URL object
loginUrl.searchParams.append('next', next);
}
//redirect the user to the full URL from the URL Object
window.location.href = loginUrl.href.toString()
}
}
}, []) //make the function run only once when the component mounts
Here's what we have done so far.
When a user that is not authenticated tries to visit any page in the dashboard for example http://my-website.com/dashboard/update-profile
, he will be redirected to http://my-website.com/login?next=http://my-website.com/dashboard/update-profile
.
Now, here's something to have in mind.
The browser will try to encode the value in the next
query parameter because it is a URL and before we access this value, we need to decode it.
On my end, here's what my address bar looks like
It is time for us to handle the redirect if the user becomes authenticated.
HANDLING THE REDIRECT
Now on your login page, we will create a variable that will store the default link the user will be redirected to if authentication is successful.
We will also import useLocation
from react-router-dom
so that we can be able to read the current URL and check if it contains a search (query) parameter.
import {useLocation} from 'react-router-dom';
export default function Login(){
//invoke the function
const location = useLocation();
//default page to redirect user after login
let redirect = 'http://my-website.com/dashboard/home';
//check if there's search param in the URL
if(location.search){
//---
}
}
If you don't want to use the useLocation
module to read the current URL, you can equally access the current URL directly using JavaScript.
export default function Login(){
//default page to redirect user after login
let redirect = 'http://my-website.com/dashboard/home';
//create a URL object using the current url
const url = new URL(window.location.href)
//check if url contains a search parameter
if(url.search){
//---
}
}
Whichever method you choose to use, the next thing to do is to read the search parameters and check if it contains next
.
If it contains next
, we will decode the value and reassign the value of the redirect
variable to this URL.
You can also perform a search to check if the decoded value contains /dashboard
.
export default function Login(){
//default page to redirect user after login
let redirect = 'http://my-website.com/dashboard/home';
//create a URL object using the current url
const url = new URL(window.location.href)
//check if url contains a search parameter
if(url.search){
//read the search parameters
const search = new URLSearchParams(url.search)
//check if next parameter is present
if(search?.get('next')){
//decode it
const next = decodeURIComponent(search.get('next'))
//check if dashboard is present in the URL
if(next.match(new RegExp('/dashboard', 'i'))){
redirect = next;
}
}
}
//after authentication, redirect users to the redirect variable
//window.location.href = redirect;
}
So after authentication, you should redirect your users to the value of the redirect
variable, which is the decoded URL!
Watch my implementation below
A LITTLE TIP
If you want to make your redirects cleaner, you can store the URL in the browser's sessionStorage
and when you validate it, you can go ahead and delete it from the session storage, then redirect the user to the URL.
Thank you for reading.
Psst! I'm open to gigs on web development and Technical Writing!
EXTRA
I built a JavaScript Library that is capable of validating your front-end forms using regular expressions, validation rules, and form input attributes.
Check out this library on GitHub
Check out the Documentation
Photo Credit: Hal Gatewood On Unsplash