Is there a way on NextAuth to redirect upon login to a specific page based on session role?

E.g. - If session.role === 'teacher', redirect to '/teacher/dashboard', else - redirect to '/admin/dashboard' The NextAuth docs don't show a way to redirect based on session data: https://next-auth.js.org/configuration/callbacks#redirect-callback
Callbacks | NextAuth.js
Callbacks are asynchronous functions you can use to control what happens when an action is performed.
5 Replies
theFern
theFern2y ago
Or if there are other ways of doing this without NextAuth, I'm open to any solution as well...
deforestor
deforestor2y ago
Oh, I was just implementing this! This is how I've implemented it, but I warn you that I had to figure a way to prevent the push to happen again before loading the target page, which seems to happen with slower connections (throttled with slow 3G for testing):
const { t } = useTranslation();
const router = useRouter();
const [isLoadingRoute, setIsLoadingRoute] = useState(false);

const session = useSession();

useEffect(()=>{
if (session.data && !isLoadingRoute){
switch (session.data.role) {
case 'RECEPTIONIST':
router.push('/reception');
break;
case 'PET_OWNER':
router.push('/clients');
break;
case 'VET':
router.push('/vet');
break;
case 'ADMIN':
router.push('/admin');
break;
default:
}
setIsLoadingRoute(true);
}
})
const { t } = useTranslation();
const router = useRouter();
const [isLoadingRoute, setIsLoadingRoute] = useState(false);

const session = useSession();

useEffect(()=>{
if (session.data && !isLoadingRoute){
switch (session.data.role) {
case 'RECEPTIONIST':
router.push('/reception');
break;
case 'PET_OWNER':
router.push('/clients');
break;
case 'VET':
router.push('/vet');
break;
case 'ADMIN':
router.push('/admin');
break;
default:
}
setIsLoadingRoute(true);
}
})
If anyone knows a better solution for this problem, that would be nice remember that the session object actually depends on how you implemented it on the [...nextauth]
Ambushfall
Ambushfall2y ago
Sorry to bump the question, but isn't Authorization a completely different thing than Authentication? Upon getting re-directed to the main page after Login check current user Authorization. Those are completely two different things, if I'm not mistaken. I'd like to hear what you think about it honestly.
theFern
theFern2y ago
@lukacolic Yes, I think you're totally right. I thought there would be a more direct way of doing from NextAuth but re-directing from main page seems like the most logical. @deforestor Thanks! This seems like a pretty good approach although I would probably would not use useEffect. Perhaps something more like what Theo explains in this video: https://youtu.be/h6wBYWWdyYQ?t=618
Theo - ping․gg
YouTube
Authentication: It’s Easier Than You Think
I get a LOT of questions about auth so I figured it was time for a video! We talk all about authentication and authorization. Watch rants like this live on https://twitch.tv/theo LIVE EVERY WEDNESDAY AT ROUGHLY 1PM PT Twitch: https://twitch.tv/theo Twitter: https://twitter.com/t3dotgg Instagram: https://instagram.com/fakiebigfoot Everywhere els...
deforestor
deforestor2y ago
thank you! That's exactly what I needed too hahaha @theFern, I just cleaned my solution a little more, to get rid of any possible errors and/or bugs: Instead of using an useEffect in the component, I sent that useEffect into a hook that does the redirection and also makes sure it doesn't try to redirect again while the page is loading:
export const useRoleRedirection = () => {
const router = useRouter();
const [isLoadingRoute, setIsLoadingRoute] = useState(false);

const session = useSession();

useEffect(() => {
if (session.data && !isLoadingRoute) {
switch (session.data.role) {
case 'CLIENT':
router.push('/client');
break;
case 'USER':
router.push('/user');
break;
case 'ADMIN':
router.push('/admin');
break;
default:
}
}
const handleRouteChange = () => {
setIsLoadingRoute(true);
};
const handleRouteComplete = () => {
setIsLoadingRoute(false);
};

router.events.on('routeChangeStart', handleRouteChange);
router.events.on('routeChangeComplete', handleRouteComplete);

return () => {
router.events.off('routeChangeStart', handleRouteChange);
router.events.off('routeChangeComplete', handleRouteComplete);
};
});
};
export const useRoleRedirection = () => {
const router = useRouter();
const [isLoadingRoute, setIsLoadingRoute] = useState(false);

const session = useSession();

useEffect(() => {
if (session.data && !isLoadingRoute) {
switch (session.data.role) {
case 'CLIENT':
router.push('/client');
break;
case 'USER':
router.push('/user');
break;
case 'ADMIN':
router.push('/admin');
break;
default:
}
}
const handleRouteChange = () => {
setIsLoadingRoute(true);
};
const handleRouteComplete = () => {
setIsLoadingRoute(false);
};

router.events.on('routeChangeStart', handleRouteChange);
router.events.on('routeChangeComplete', handleRouteComplete);

return () => {
router.events.off('routeChangeStart', handleRouteChange);
router.events.off('routeChangeComplete', handleRouteComplete);
};
});
};
Want results from more Discord servers?
Add your server