Redirect inside of middleware not updating url
Unanswered
Willow Ptarmigan posted this in #help-forum
Willow PtarmiganOP
Hey all,
I am running into an issue where I have redirect inside of my middleware to a complete profile flow if a user has to complete some profile information. it seems to work fine, but im finding that after a user signs in and triggers this redirect that the complete profile component is rendered but the url hasnt been updated .
I am using authjs v5, beta 19 to handle my auth and i have put that inside of a form action.
Here is my middleware:
I am running into an issue where I have redirect inside of my middleware to a complete profile flow if a user has to complete some profile information. it seems to work fine, but im finding that after a user signs in and triggers this redirect that the complete profile component is rendered but the url hasnt been updated .
I am using authjs v5, beta 19 to handle my auth and i have put that inside of a form action.
Here is my middleware:
import { NextResponse } from "next/server";
import { auth } from "./auth";
import * as Routes from "@/constants/routes";
const isProtectedRoute = (pathname: string) => {
return (
pathname.startsWith(Routes.ADMIN) ||
pathname.startsWith(Routes.DASHBOARD) ||
pathname.startsWith(Routes.HOME) ||
pathname.startsWith(Routes.ACCOUNT) ||
pathname.startsWith(Routes.SETTINGS) ||
pathname.startsWith(Routes.COMMISSION_PORTFOLIO)
);
};
export default auth((req) => {
console.log("------ auth middleware ------");
console.log("req.url:", req.url);
// if the user is not logged in and is trying to access a protected route
// redirect them to the sign-in page
if (isOnProtectedRoute && !isLoggedIn) {
return NextResponse.redirect(new URL(Routes.SIGN_IN, req.nextUrl));
}
// if the user is logged in and has not completed their profile
// redirect them to the complete profile page
if (isLoggedIn && req.auth?.user.isProfileComplete === false) {
// check if the user is already on the complete profile page
// to prevent an infinite redirect loop
if (req.nextUrl.pathname !== Routes.COMPLETE_PROFILE) {
return NextResponse.redirect(
new URL(Routes.COMPLETE_PROFILE, req.nextUrl)
);
}
}
return NextResponse.next();
});
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
};35 Replies
Willow PtarmiganOP
This is my server action in my signin form:
"use server";
{.........}
export async function signInAction(
prevState: SignInActionFormState,
rawFormData: FormData
): Promise<SignInActionFormState> {
console.log("signInAction");
// Convert FormData to object
const formData = Object.fromEntries(rawFormData);
const parsed = SignInFormSchema.safeParse(formData);
console.log("parsed", parsed);
// get the fields from the form data
const fields: Record<string, string> = {};
for (const key of Object.keys(formData)) {
fields[key] = formData[key].toString();
}
// if the form data is invalid, return an error message
if (!parsed.success) {
return {
message: undefined,
fieldErrors: parsed.error.flatten().fieldErrors,
fields,
};
}
try {
const res = await signIn("credentials", {
username: parsed.data.username,
password: parsed.data.password,
redirect: false, // Prevent automatic redirect
});
if (res?.error) {
return { success: false, message: res.error };
}
if (res?.url) {
redirect(res.url);
}
// Successful sign-in, redirect to dashboard
redirect(Routes.DASHBOARD);
} catch (error) {
console.log("error in sign in");
// we are using the error message to determine if this is a redirect
// from authjs, if it is a redirect, we want to rethrow the error
// so that nextjs can handle the redirect
// this is because we are doing a client side redirect inside of a server action
if (isRedirectError(error)) {
console.log("error in sign in: NEXT_REDIRECT: ", error);
// This is a redirect, not an actual error
throw error;
}
console.error("SignIn error:", error);
return {
success: false,
message: "An error occurred during sign in. Please try again later.",
};
}
}when I try and trace what is happening in the middleware this is all im seeing:
and as stated above, the page for my profile complete is being rendered but the url is not correct.
Thanks in advance for any help
------ auth middleware ------
req.url: http://localhost:3000/dashboard
------ auth middleware ------
req.url: http://localhost:3000/sign-up/complete-profileand as stated above, the page for my profile complete is being rendered but the url is not correct.
Thanks in advance for any help
Willow PtarmiganOP
bump
When redirected in mw you need to use the actual url not localhost it doesn’t resolve local host to the proper spot. I didn’t read through all your code cause I’m on mobile.
Let me know if that helps
Willow PtarmiganOP
when the redirection doesnt have a hard coded host, the logs are from me running the code locally.
In my middleware iam doing this to redirect:
In my middleware iam doing this to redirect:
return NextResponse.redirect(
new URL(Routes.COMPLETE_PROFILE, req.nextUrl)
);So what’s routes.Completeprofile? You shouldn’t need the second argument.
Log those out in something like console.log(“routes.completeProfile\req.nexturl).
On my phone so sorry for typos or code block.
On my phone so sorry for typos or code block.
Willow PtarmiganOP
Routes.COMPLETE_PROFILE is a relative route so the second param is needed since i pull the base from the requestI mean still log it out and make sure the URL is valid.
Willow PtarmiganOP
this is the output:
req.nextUrl: http://localhost:3000/dashboard
redirect url: http://localhost:3000/sign-up/complete-profile
redirect url: http://localhost:3000/sign-up/complete-profile
this is using the case of user logs in, calles authjs signin from an action. The action is then redirecting to /dashboard, but the middleware is picking up that they havent finished their profile yet, so it redirects to /sign-up/complete-profile.
then the same issue happen where after this inital signup, the user ui is the contents of /sign-up/complete-profile but the url is /dashboard
then the same issue happen where after this inital signup, the user ui is the contents of /sign-up/complete-profile but the url is /dashboard
I think you need to redirect to the actual url
@Willow Ptarmigan
unless its actually running on local host
middleware is weird, gotta have the actual url cant say localhost
Willow PtarmiganOP
its running on my local machine
Interesting... hrmmm
Can you try just doing the redirect without using
something like
new URL() idk if itll make a difference.... lol something like
return NextResponse.redirect(`${process.env.LocalURL}${redirectCookie.value}`);Thats what I do in my middleware. Or at the very least to string the
new url() object, it might not like it being passed in.Just spitballing ideas
Willow PtarmiganOP
redirect using hardcoded url results in the same issue
That is really strange... I dont understand how....
Id have to have the repo local to look further into it I think
Or if you can reproduce in a smaller project maybe?
Willow PtarmiganOP
yeah i try and get something up and running i think at smaller scale
Willow PtarmiganOP
I wonder if it has something todo with authjs's middleware wrapper? I tried making. super simple example with out authjs and it seemed to work fine
the only thing im doing different might just be using authjs's auth middleware wrapper
Willow PtarmiganOP
bump
I would reach out on the auth js discord or GitHub. Unfortunately I don’t use any auth library so I am of little help without a lot of work on my part.
Willow PtarmiganOP
yeah ive already posted it over there. just waiting on something actionable
thanks for the help
Willow PtarmiganOP
so still trying to figure this out but I stumbled upon this post:
https://github.com/vercel/next.js/issues/65936
https://github.com/vercel/next.js/issues/65936
Willow PtarmiganOP
now im wondering if auth middleware redirects are the correct way of dealing with my use case?