Next.js Discord

Discord Forum

Google provider not working, I think issue related to my auth config role based redirection

Unanswered
Russian Blue posted this in #help-forum
Open in Discord
Avatar
Russian BlueOP
import type { NextAuthConfig, Session } from "next-auth";

import {
  DEFAULT_LOGIN_REDIRECT,
  publicRoutes,
  authRoutes,
  apiAuthPrefix,
  adminPrefix,
} from "./routes";
import { UserRole } from "@prisma/client";
export const authConfig = {
  pages: {
    signIn: "/auth/login",
    error: "/auth/error",
  },
  providers: [],
  callbacks: {
    async authorized({ auth, request: { nextUrl } }) {
      const isLoggedIn = !!auth?.user;
      const isPublicRoute = publicRoutes.includes(nextUrl.pathname);
      const isAuthRoute = authRoutes.includes(nextUrl.pathname);
      const isApiAuthRoute = nextUrl.pathname.startsWith(apiAuthPrefix);
      const isAdminRoute = nextUrl.pathname.startsWith(adminPrefix);

      if (isAdminRoute) {
        const user = auth?.user;
        return user?.role !== UserRole.ADMIN;
      }

      if (isApiAuthRoute) return false; //so if someone goes to that page is not allowed

      if (isAuthRoute) {
        if (isLoggedIn) {
          return Response.redirect(new URL(DEFAULT_LOGIN_REDIRECT, nextUrl));
        }
        return true;
      }
      // if (!isLoggedIn && !isPublicRoute) {
      //   return Response.redirect(new URL("/auth/login", nextUrl));
      // }
      if (!isPublicRoute && !isLoggedIn) {
        return false;
      }
      return true;
    },
  },
} satisfies NextAuthConfig;

41 Replies

Avatar
Ray
remove this line
if (isApiAuthRoute) return false;
btw this should be
return user?.role !== UserRole.ADMIN; -> return user?.role === UserRole.ADMIN;
if authorized callback return false, it will redirect the user to pages.signIn
Avatar
Russian BlueOP
but this has the api/auth/providers route
or its fine?
Avatar
Ray
how do people sign in if you protect this api?
Avatar
Russian BlueOP
mmm honestly you have a point, but why would they put it like this in the tutorial?
Avatar
Ray
what tutorial?
Avatar
Russian BlueOP
one on youtube by codewithantonio
but yesterday we changed everything in any case lol i think it wasn't correct his implementation
Avatar
Russian BlueOP
with this code however
Image
I cannot access my register page
Avatar
Ray
is your register page inside publicRoutes
Avatar
Russian BlueOP
it is inside authRoutes
better to get rid of all authRoutes and place them inside publicRoutes right? for simplicity
since they actually are accessible if user not logged in
Avatar
Ray
set a isProjectedRoute then change this
if (isProtectedRoute) {
  return isLoggedIn
} else if (isLoggedIn) {
 return Response.redirect()
}
Avatar
Russian BlueOP
but I don't know all my protected routes
that's why I went with !publicRoutes since they are usually less than protected
Avatar
Ray
if (!isPublicRoute) {
  if (isLoggedIn || nextUrl.pathname === '/register') return true;
  return false
}
Avatar
Russian BlueOP
Hello again ray
here is the final version of the code:
   async authorized({ auth, request: { nextUrl } }) {
  
      const isLoggedIn = !!auth?.user;
      const isAdminRoute = nextUrl.pathname.startsWith(adminPrefix);
      const isPublicRoute = publicRoutes.includes(nextUrl.pathname);
      const isAuthRoute = authRoutes.includes(nextUrl.pathname);

      if (isAuthRoute && isLoggedIn) {
        return Response.redirect(new URL(DEFAULT_LOGIN_REDIRECT, nextUrl)); //we pass nextUrl to create an absolute url prefixed with localhost:3000
      }

      if (isAdminRoute) {
        const user = auth?.user;
        return user?.role === UserRole.ADMIN;
      }

      if (!isLoggedIn && !isPublicRoute && !isAuthRoute) {
        return Response.redirect(new URL("/auth/login", nextUrl));
      }


      return true;
    
    },
only oAuth not working
Avatar
Ray
why you redirecting isAuthRoute to default login?
Avatar
Russian BlueOP
if they are logged in
default login redirect is the home dashbaord
Avatar
Ray
no don't
just skip them
Avatar
Russian BlueOP
why? how?
return false?
Avatar
Ray
no remove isAuthRoute in here
Avatar
Russian BlueOP
oh okay get you
but now i can access login even if I am already logged in
Avatar
Ray
if (nextUrl.pathname === '/login && isLoggedIn) {
Avatar
Russian BlueOP
return false?
or redirect
Avatar
Ray
return false if you want to redirect to pages.signIn
Avatar
Russian BlueOP
awesome, for reference here is the latest version of the code, and it is working perfectly fine now with all providers.
 async authorized({ auth, request: { nextUrl } }) {
      const isLoggedIn = !!auth?.user;
      const isAdminRoute = nextUrl.pathname.startsWith(adminPrefix);
      const isPublicRoute = publicRoutes.includes(nextUrl.pathname);
      const isAuthRoute = authRoutes.includes(nextUrl.pathname);
      const isApiAuthRoute = nextUrl.pathname.startsWith(apiAuthPrefix);
      if (isApiAuthRoute) {
        return true; //automatic allowing for anyone trying to signin from any provider, we are explicitly stating it here to ensure we aren't rejecting this route somewhere below
      }
      if (isAuthRoute && isLoggedIn) {
        return false; //automatically redirect to signinPage
        // return Response.redirect(new URL(DEFAULT_LOGIN_REDIRECT, nextUrl)); //we pass nextUrl to create an absolute url prefixed with localhost:3000
      }

      if (isAdminRoute) {
        const user = auth?.user;
        return user?.role === UserRole.ADMIN;
      }

      if (!isLoggedIn && !isPublicRoute && !isAuthRoute) {
        return Response.redirect(new URL("/auth/login", nextUrl));
      }

      return true;
    },
Thank you for the help! Any suggestions for best practices in the code while mainting proper functionality?