I want to implement a simple login flow. I have a login form that takes the user's phone and password. The credentials are sent to the API after submitting the form by calling the login
function (mutation function returned by the Tanstack Query useMutation
hook). Inside the onSuccess
callback of the mutation function, I set the token
value returned by the API as a cookie using the setCookie
function of the cookies-next package (version: 4.2.1), and also redirect the user to the /projects
route using useRouter()
from next/navigation
:
const { login, isLoggingIn } = useLogin();
const router = useRouter()
const onSubmit = ({ phone, password }) => {
login(
{ phone, password },
{
onSuccess: ({ data: { token } }) => {
setCookie("token", token);
router.push('/projects')
},
}
);
};
For protecting my routes, I use middleware:
import { getCookie } from "cookies-next";
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
export const config = {
matcher: "/((?!api|_next/static|_next/image|assets|favicon.ico|verify-email).*)",
};
export async function middleware(req: NextRequest) {
const res = NextResponse.next();
const token = getCookie("token", { req, res });
const isAuthRoute = req.nextUrl.pathname === "/auth";
if (!token && !isAuthRoute) {
return NextResponse.redirect(new URL("/auth", req.url));
}
if (token && isAuthRoute) {
return NextResponse.redirect(new URL("/projects", req.url));
}
return res;
}
The code works perfectly without any issues on development (http://localhost:3000/). The user fills out the form, the form gets submitted and form data is sent to the API. The API responds back with the token. The token gets set in the browser's cookies and user gets redirected successfully. The issue occurs when I push the code to production and also when I run npm run build
and then npm run start
on my local machine. After submitting the form, the token is provided by the backend and is set successfully as cookie (Checked the browser cookies). But the part where the user must get redirected is not working.
Then if you wait for about 30 seconds and submit the form again, the page gets redirected successfully this time!
Also, if you Refresh the page after the first submit, since the token is set to cookies, the page gets redirected to /projects
by the middleware.
These are what I've tried so far to solve the issues:
NextResponse.rewrite()
instead of NextResponse.redirect()
router.refresh()
before running router.push()
NextResponse.redirect(new URL("/auth", req.url), { status: 303 })
I must mention that I use:
Note: My .env
files content are identical for both development and production.
Edit: I removed the whole middleware.ts
and everything works fine, and user gets redirected to /projects
! Therefore, it look like the problem lies in the middleware.
I appreciate any help anyone could kindly provide.
Not sure why but based on this comment, using the whole website url somehow fixed the problem. Here is how I modified my code:
// middleware.ts
if (token && isAuthRoute) {
return NextResponse.redirect(new URL("htttps://mysite.com/projects", req.url));
}