Reputation: 363
I have a simple project that I built that protects the routes/pages of the website by using the if and else statement and putting each page with a function withAuth()
, but I'm not sure if that is the best way to protect routes with nextjs, and I noticed that there is a delay in protecting the route or pages, like 2-3 seconds long, in which they can see the content of the page before it redirects the visitor or unregistered user to the login page.
Is there a way to get rid of it or make the request faster so that unregistered users don't view the page's content? Is there a better approach to safeguard a certain route in the nextjs framework?
import { useContext, useEffect } from "react";
import { AuthContext } from "@context/auth";
import Router from "next/router";
const withAuth = (Component) => {
const Auth = (props) => {
const { user } = useContext(AuthContext);
useEffect(() => {
if (!user) Router.push("/login");
});
return <Component {...props} />;
};
return Auth;
};
export default withAuth;
import React from "react";
import withAuth from "./withAuth";
function sample() {
return <div>This is a protected page</div>;
}
export default withAuth(sample);
Upvotes: 1
Views: 12133
Reputation: 4021
With Customized 401 Page
We are going to first define our customized 401 page
import React from "react"
const Page401 = () => {
return (
<React.Fragment>
//code of your customized 401 page
</React.Fragment>
)
}
export default Page401
Now, we are going to change a small part of the code kiranr shared
export async function getServerSideProps({ req }) {
const { token } = cookie.parse(req.headers.cookie)
const userRes = await fetch(`${URL}/api/user`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`
}
})
const data = await userRes.json()
// does not allow access to page if not logged in
if (!data.username) {
//THIS PART CHANGES
return {
props: {
unauthorized: true
}
}
//THIS PART CHANGES
}
return {
props: { data }
}
}
Then we will check this 'unauthorized' property in our _app.js file and call our customized 401 page component if its value is true
import Page401 from "../components/Error/Server/401/index";
const App = ({ Component, pageProps }) => {
//code..
if (pageProps.unauthorized) {
//if code block reaches here then it means the user is not authorized
return <Page401 />;
}
//code..
//if code block reaches here then it means the user is authorized
return (
<Provider store={store}>
<Component {...pageProps} />
</Provider>
)
}
Upvotes: 2
Reputation: 2465
you can make the authentication of user on server-side, if a user is logged in then show them the content of the protected route else redirect them to some other route. refer to this page for mote info.
in getServerSideProps
check whether the user has logged in
if (!data.username) {
return {
redirect: {
destination: '/accounts/login',
permanent: false,
},
}
}
here's complete example of protected route page
export default function SomeComponent() {
// some content
}
export async function getServerSideProps({ req }) {
const { token } = cookie.parse(req.headers.cookie)
const userRes = await fetch(`${URL}/api/user`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`
}
})
const data = await userRes.json()
// does not allow access to page if not logged in
if (!data.username) {
return {
redirect: {
destination: '/accounts/login',
permanent: false,
},
}
}
return {
props: { data }
}
}
Upvotes: 6