-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
no redirection after successful login #10016
Comments
There are a lot of bugs in version 5. It better try to create an auth flow from scratch or rollback to v4. |
With this could you probably have /had a similar issue to mine: Anyone familiar with this issue? I do not want to perform a whole page refresh upon login / logout. This sucks. |
My session is initialized / fetched in the root layout with This session is passed to the SessionProvider. In i.e. the AppBar / NavBar, where I have a user button or a login button based on session status, I retrieve the session with When I log the Upon manual page refresh (or window.location.refresh) the session is passed down correctly and my AppBar useSession returns the proper data. Recently I discovered that the same issue exists for the auth logout. If redirect is set to false, the logout doesn't actually happen on client side and the session isn't updated until manual page refresh. The whole situation is all about these annoying page refreshes. I do not wanna reload the entire app upon login/logout, i just want the ui to represent the actual session as anyone would expect. I will share code later when I get home, unless you have any ideas based on this description already? |
I actually finally made it work thanks to another very recent github issue (cannot find it anymore tho lol) The underlying issue was that The solution was to build a custom "use client";
import { Session } from "next-auth";
import {
SessionProvider as NextSessionProvider,
getSession
} from "next-auth/react";
import { usePathname } from "next/navigation";
import {
ReactNode,
useCallback,
useEffect,
useState
} from "react";
// Retrieve user session for the app's session context
export default function SessionProvider({
children
}: {
children: ReactNode;
}) {
const [ session, setSession ] = useState<Session | null>(null);
const pathName = usePathname();
const fetchSession = useCallback(async () => {
try {
const sessionData = await getSession();
setSession(sessionData);
} catch (error) {
setSession(null);
if (process.env.NODE_ENV === "development") {
console.error(error);
}
}
}, []);
useEffect(() => {
fetchSession().finally();
}, [fetchSession, pathName]);
return (
<NextSessionProvider session={session}>
{children}
</NextSessionProvider>
);
} Now I can use I am very happy as I finally figured this out, it's been plagueing me for almost 2 months by now. |
I am facing something like you This is my root layout code export default function RootLayout({ children, session }: IProps) { const handleSignOut = async () => { return ( {children}
) /////////////////////////////////////////////////////////////////////////////////////////////////////////////// import { NextResponse } from 'next/server' export async function middleware(request: any) { // Check if session exists or not export const config = { |
Well I think by their documentation:
So we are not supposed to |
Session change was not visible on client as Auth.js login and signout stopped refreshing the page solution to implement Session provider with getSession() rather than auth() refer: nextauthjs/next-auth#10016 (comment) also fixed Skeleton Lint issues in Loading 🚨
with server action I use 'use server';
import { signIn } from '@/lib/auth';
import { AuthError } from 'next-auth';
import { redirect } from 'next/navigation';
export async function authenticate(_: string | undefined, formData: FormData) {
try {
await signIn('credentials', formData);
} catch (error) {
if (error instanceof AuthError) {
switch (error.type) {
case 'CredentialsSignin':
return 'Invalid credentials.';
default:
return 'Something went wrong.';
}
}
throw error;
} finally {
redirect('/'); // or your pathname
}
} and client ...
const [errorMessage, dispatch] = useFormState(authenticate, undefined);
return (
<form action={dispatch} className="..">
... |
Placing export async function authenticate(
prevState: string | undefined,
formData: FormData,
) {
let errorOccurred = false;
try {
await signIn('credentials', formData);
} catch (error) {
if (error instanceof AuthError) {
errorOccurred = true;
switch (error.type) {
case 'CredentialsSignin':
return 'Invalid credentials.';
default:
return 'Something went wrong.';
}
}
throw error;
} finally {
if (!errorOccurred) {
redirect('/your-pathname');
}
}
} Note that |
This comment has been minimized.
This comment has been minimized.
It works, thanks! Saved my life! |
I found solution without modifying SessionProvider. I use "next-auth": "^5.0.0-beta.19",
"next": "^14.2.3", You have to properly split codebase to server/client part. According to Next 14 App Router guidelines. So, guys, I got your back! Follow these steps1. Create
|
I don't get it mine goes to the home route when I have clearly specified to rediret to the '/admin' and only after refresh do I get the correct behaviour export default auth((req) => { const isApiAuthRoute = nextUrl.pathname.startsWith(apiPrefix); // TODO: remove this on prod if (isApiAuthRoute || isAuthRoute || isPublicRoute) { if (!isAdminRoute && isLoggedIn) { if (isAdminRoute && isLoggedIn) { return Response.redirect(new URL("/auth/login", nextUrl)); // Optionally, don't invoke Middleware on some paths |
Using this component, the session is not even updated after reloading lol. This cannot possibly work as it does the exact same thing useSession(). |
Doesn't this cause your whole app to be dynamically rendered, instead of having static & dynamic pages? |
I had the same issue with custom login page, adding this to custom login page fixed the issue for me (or hid it)
|
I solved issue in server action by adding isRedirectError, in my actions/auth.ts file export async function doLogin(formData: z.infer<typeof signInSchema>, callbackUrl = DEFAULT_LOGIN_REDIRECT) {
try {
....
await signIn('credentials', {
redirectTo: callbackUrl,
email: parsedCredentials.data.email,
password: parsedCredentials.data.password,
remember: parsedCredentials.data.remember,
});
} catch (e: unknown) {
if (isRedirectError(e)) throw e;
....
const nextError = e as AuthError;
const error = nextError.cause?.err as CustomError;
// Handle unexpected CustomError types
return {success: false, error: {message: 'An unexpected error occurred.'}};
}
} |
Still facing this issue with the latest version of NextAuth and NextJs |
Here’s the workaround I implemented for handling the redirection along with the callback URL after login. I would appreciate feedback from the community and the developers of NextAuth.js to confirm whether this is a good approach. On the Login Page (Page)import { useSearchParams } from 'next/navigation';
export default function LoginPage() {
const searchParams = useSearchParams();
const callbackUrl = searchParams.get('callbackUrl');
return (
<main className="flex items-center justify-center md:h-screen">
{/* Other components */}
<LoginForm callbackUrl={callbackUrl} />
{/* Other components */}
</main>
);
} Passing the
|
For the record, still facing this issue as of today
@lespons workaround (+ @weijyun9008 correction) worked for me |
I'm using [email protected] and in my case there wasn't redirection because of next_redirect error was occured. The reason was in catch block where I didn't throw error object: try {
await signIn(......);
} catch (error) {
return { success: false, message: "auth error" };
} Note, you should have this part in the end of catch block: catch (error) {
................
throw error;
} |
even with this I am still facing this error |
for client complements ONLY you should use "useRouter" hook, it will save the day: const onSubmit = async (values: z.infer<typeof LoginSchema>) => {
setError("");
setSuccess("");
setIsLoading(true);
const res = await signIn("custom_credentials", {
redirect: false,
redirectTo: '/',
email: values.email,
password: values.password,
});
setIsLoading(false);
if (res?.error) {
if (res?.error === "CredentialsSignin") {
setError("كلمة المرور أو البريد الإلكتروني غير صحيح");
}
} else {
setSuccess("تم تسجيل الدخول بنجاح");
router.push('/')
}
};
}; so this is the escape router.push('/') |
signIn('credentials', {
username: formData.get('username'),
password: formData.get('password'),
redirectTo: formData.get('redierctTo')?.toString() ?? '/',
}) |
NextAuthProvider'use client'
import type { Session } from "next-auth"
import { SessionProvider } from "next-auth/react"
export default function NextAuthSessionProvider({ children, session }: { children: React.ReactNode, session: Session | null }) {
return <SessionProvider session={session}>{children}</SessionProvider>
} Actions'use server';
import { signIn } from '@/auth';
import { AuthError } from 'next-auth';
export async function authenticate(
prevState: string | undefined,
formData: FormData,
) {
try {
const username = formData.get('username')
const password = formData.get('password')
const callbackUrl = formData.get('callbackUrl')
await signIn('credentials', {
username,
password,
redirect: true,
redirectTo: String(callbackUrl)
})
} catch (error) {
if (error instanceof AuthError) {
switch (error.type) {
case 'CredentialsSignin':
return 'Invalid credentials.';
default:
return 'Something went wrong.';
}
}
throw error;
}
} LoginForm'use client'
import { useActionState } from "react"
import { authenticate } from "@/app/lib/actions"
import { useSearchParams } from "next/navigation"
export default function Page() {
const [errorMessage, formAction, isPending] = useActionState(
authenticate,
undefined
)
const search = useSearchParams()
const callbackUrl = search.get('callbackUrl') ?? '/'
return (
<form action={formAction} className="grid grid-cols-1 gap-4">
<input type="text" name="username" defaultValue="super" />
<input type="text" name="password" defaultValue="123456" />
<input type="hidden" name="callbackUrl" defaultValue={callbackUrl} />
<button type="submit">Login</button>
</form>
)
} I had to refresh pageScreenbits.2024-12-13_183607.mp4Npm Package
|
still having an issue and my user return null.
|
Found a solution. u need to handle it on different function and call this function when the handleSubmitForm is returning something, either it's client side or server side. it's also takes time for the jwt token to register in the cookies depends on your providers callback.
|
Environment
System:
OS: macOS 14.1.2
CPU: (8) arm64 Apple M2
Memory: 489.31 MB / 16.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 20.7.0 - /opt/homebrew/bin/node
Yarn: 1.22.21 - /opt/homebrew/bin/yarn
npm: 10.1.0 - /opt/homebrew/bin/npm
pnpm: 8.14.0 - /opt/homebrew/bin/pnpm
Browsers:
Chrome: 121.0.6167.160
Safari: 17.1.2
npmPackages:
next: 14.1.0 => 14.1.0
react: 18.2.0 => 18.2.0
Reproduction URL
https://github.com/78raoul78/ui
Describe the issue
After a successful signIn, I'm not getting redirected to my home page even though the callbackUrl is correctly set.
How to reproduce
Expected behavior
After a successful login, I'm expecting to be redirected to the initial url (the one before the redirection) which is localhost:3001
The text was updated successfully, but these errors were encountered: