Several Improvements Needed for signIn and signOut Logic in `Chapter 15 Adding Authentication` of the Official `dashboard-app` Tutorial
currently,The implementation of next-auth Credentials authentication flow in Chapter 15 of the official tutorial works, but it has some flaws that cause several confusion for me and also some other learners. such as
Existing Issues
Based on my observations, the following issues exist with the tutorial's implementation (which can be reproduced in the official live demo):
- When navigating from the homepage to the login page and successfully logging in, the user is redirected to the
/dashboardpage, but the browser's URL does not change and remains as/login. Additionally, theSign Outbutton does not work until the page is refreshed, after which the URL displays correctly as.../dashboardand theSign Outbutton works as expected.
https://github.com/user-attachments/assets/bfa5979d-05d6-41ab-9b81-bde9a07a4466
- Following the steps in point 1, when clicking the Sign Out button on any page (e.g.,
/dashboard/customers), the page content updates to the/loginpage, but the browser's URL does not change. After refreshing the page, the browser URL updates to.../login?callbackUrl=https%3A%2F%2Fnext-learn-dashboard.vercel.sh%2Fdashboard%2Fcustomers.
https://github.com/user-attachments/assets/e0153cee-1b0d-400b-9306-321428283e1a
- Following the steps in point 2, if the browser URL contains a
callbackUrl=...query parameter (e.g., when accessinghttps://next-learn-dashboard.vercel.sh/dashboard/customerswhile not logged in, which redirects to the/loginpage with thecallbackUrl), the expected behavior is to be redirected to thecallbackUrlpage after a successful login. However, after logging in, the user is still redirected to the/dashboardpage, and the same issue from point 1 occurs: the browser's URL does not update and remains as.../login?callbackUrl=https%3A%2F%2Fnext-learn-dashboard.vercel.sh%2Fdashboard%2Fcustomers, and theSign Outbutton does not work. Refreshing the page resolves the issue.
https://github.com/user-attachments/assets/4dd22877-1e4b-42f8-a471-08b99ff87959
Suggested Improvements
During SignIn
As mentioned in this comment Redirect URL not updating correctly in browser after successful redirect, pass the redirectTo parameter to the signIn() function, and ensure it aligns with the logic in auth.config.ts -> authorized.
The logic in auth.config.ts -> authorized:
// ...
if (isOnDashboard) {
if (isLoggedIn) {
return true;
}
return false;
} else if (isLoggedIn) {
return Response.redirect(new URL('/dashboard', nextUrl));
}
// ...
To keep the same logic, the login form should include the redirectTo field, defaulting to /dashboard. If the URL contains a callbackUrl, the field should be set to that value.
modify app/login/page.tsx:
// ...
export default function LoginPage({
searchParams,
}: {
searchParams?: {
callbackUrl?: string;
};
}) {
const redirectTo = searchParams?.callbackUrl || '/dashboard'; // <============== get `redirectTo` from search param `callbackUrl`
return (
<main className="flex items-center justify-center md:h-screen">
{/* ... */}
<LoginForm redirectTo={redirectTo} /> {/* <============== pass `redirectTo` to LoginForm */}
</div>
</main>
);
}
modify app/ui/login-form.tsx:
// ...
export default function LoginForm({ redirectTo }: { redirectTo: string }) {
// ...
return (
<form action={formAction} className="space-y-3">
{/* ... */}
<input type="hidden" name="redirectTo" value={redirectTo} /> {/* <============== add `redirectTo` */}
{/* ... */}
)
}
During SignOut
In the sidenav.tsx, the redirectTo parameter should be specified. Typically, when signing out, the user should be redirected to the homepage or the login page.
modify app/ui/dashboard/sidenav.tsx:
// ...
export default function SideNav() {
return (
{/* ... */}
<form
action={async () => {
'use server';
await signOut({ redirectTo: '/' }); /* <============== add `redirectTo` */
}}
>
{/* ... */}
)
}
Verification After the Fixes
minimal reproducible repo: https://github.com/ks4na/nextjs-dashboard/tree/chapter15-improvements
vercel.app preview link
Additional Information
next-auth documentation
For more details on signIn(), signOut(), and redirectTo, see the documentation: signIn(), signOut().
I got a few errors lately that Canary is using the new async server component props... So.... just a suggestion:
// ...
type PageProps = {
searchParams?: Promise<{
callbackUrl?: string;
}>;
};
export default async function LoginPage(props: PageProps) {
const searchParams = await props.searchParams;
const redirectTo = searchParams?.callbackUrl || "/dashboard"; // <============== get `redirectTo` from search param `callbackUrl`
return (
<main className="flex items-center justify-center md:h-screen">
{/* ... */}
<LoginForm redirectTo={redirectTo} /> {/* <============== pass `redirectTo` to LoginForm */}
</div>
</main>
);
}
Thank you! Fixing