How to create HOC for auth in Next.js?
Server-side authentication
Based on the answer from Create a HOC (higher order component) for authentication in Next.js, you can create a re-usable higher-order function for the authentication logic.
If the user data isn't present it'll redirect to the login page. Otherwise, the function will continue on to call the wrapped getServerSideProps
function, and will return the merged user data with the resulting props from the page.
export function withAuth(gssp) {
return async (context) => {
const response = await fetch('http://localhost:4000/user/me');
const data = await response.json();
if (!data) {
return {
redirect: {
destination: '/admin/login'
}
};
}
const gsspData = await gssp(context); // Run `getServerSideProps` to get page-specific data
// Pass page-specific props along with user data from `withAuth` to component
return {
props: {
...gsspData.props,
data
}
};
}
}
You can then use it on the AdminHome
page to wrap the getServerSideProps
function.
const AdminHome = ({ data }) => {
return ();
};
export const getServerSideProps = withAuth(context => {
// Your normal `getServerSideProps` code here
return { props: {} };
});
export default AdminHome;
Client-side authentication
If you'd rather have the authentication done on the client, you can create a higher-order component that wraps the component you want to protect.
const withAuth = (Component) => {
const AuthenticatedComponent = () => {
const router = useRouter();
const [data, setData] = useState()
useEffect(() => {
const getUser = async () => {
const response = await fetch('http://localhost:4000/user/me');
const userData = await response.json();
if (!userData) {
router.push('/admin/login');
} else {
setData(userData);
}
};
getUser();
}, []);
return !!data ? <Component data={data} /> : null; // Render whatever you want while the authentication occurs
};
return AuthenticatedComponent;
};
You can then use it to wrap the AdminHome
component directly.
const AdminHome = () => {
return ();
};
export default withAuth(AdminHome);