0

I have an Express.js backend running on http://localhost:8000 and a Next.js frontend (App Router) running on http://localhost:3000.

What Works: • When making a request from a Next.js client component (browser) to the Express backend, cookies are set successfully. • When checking the response headers in a server component (SSR) or API route, I can see the Set-Cookie header coming from Express.

What Works: • When making a request from a Next.js client component (browser) to the Express backend, cookies are set successfully. • When checking the response headers in a server component (SSR) or API route, I can see the Set-Cookie header coming from Express.

What I Tried: • Setting credentials: "include" in the fetch request. • Making a Next.js API route as a proxy and forwarding the Set-Cookie header. • Using different SameSite policies (Lax, Strict, None with Secure). • Ensuring CORS is properly configured on Express (Access-Control-Allow-Credentials: true). • Manually setting a cookie in the Next.js response (nextResponse.cookies.set("key", "value")).

This is my SSR function on NextJS to fetch request on ExpressJS API. To get info if user is authenticated or not I am sending access token. If access token is expired and refresh token is valid then I am refreshing the access token but new access token is not adding to browser cookies.

            "use server";
        import { User } from "@/components/providers/user.provider";
        import { cookies } from "next/headers";
        import { fetcher } from "./fetcher";

        interface invalidSession {
            ok: false, message: string, code: "unauthorized" | "invalid-or-expired-token"
        }

        interface successSession {
            ok: true, message: string, data: User;
        }


        export async function getSession() {
            const accessToken = (await cookies()).get("accessToken")?.value;
            const refreshToken = (await cookies()).get("refreshToken")?.value;

            const res = await fetcher<invalidSession | successSession>("/user/info", {
                headers: {
                    Cookie: `accessToken=${accessToken}`
                }
            });

            if (!res.ok) {

                if (res.code === "invalid-or-expired-token") {
                    console.log("Invalid or expired access token");
                    console.log("refreshing token");


                    const refreshTokenRes = await fetcher<invalidSession | successSession>("/user/refresh-token", {
                        method: "POST",
                        headers: {
                            Cookie: `refreshToken=${refreshToken}`
                        }
                    });


                    if (!refreshTokenRes.ok) {
                        console.log("refresh token is invalid or expired!");
                        return null;
                    } else {
                        console.log("refresh token is valid & generated new access token!");

                        return refreshTokenRes.data
                    }
                }

                console.log("No access Token is provided!");
                return null;
            }

            console.log("access token is valid!");
            return res.data;

        }

this is my expressjs refreshToken function where i setting new accessToken but it not working as i say above. it only works when request comes from nextjs client component but not when request comes from nextjs ssr

             public async refreshToken(req: Request, res: Response) {
                const refreshToken = req.cookies.refreshToken;

                if (!refreshToken) {
                    res.clearCookie("accessToken")
                    res.clearCookie("refreshToken")
                    return ResponseHandler.unauthorized(res, "unauthorized");
                };

                try {
                    const decoded = jwt.verify(refreshToken, authConfig.auth_refresh_secret) as { id: number };
                    const user = await prisma.user.findUnique({ where: { id: decoded.id }, include: { user_verifications: true } });

                    if (!user) {
                        res.clearCookie("accessToken")
                        res.clearCookie("refreshToken")
                        return ResponseHandler.unauthorized(res, "unauthorized")
                    };

                    const verifications = user.user_verifications as user_verifications;

                    const newAccessToken = jwt.sign({ id: user.id }, authConfig.auth_secret, {
                        expiresIn: `${authConfig.auth_secret_expires_in as any}m`
                    })

                    res.cookie("accessToken", "asd", {
                        httpOnly: true,
                        secure: process.env.NODE_ENV === "production" ? true : false,
                        sameSite: "strict",
                    });

                    return ResponseHandler.success(res, {
                        accessToken: newAccessToken,
                        user: {
                            firstname: user.firstname,
                            lastname: user.lastname,
                            email: user.email,
                            email_verified: verifications.email_verified,
                            email_verified_at: verifications.email_verified_at,
                            phone: user.phone,
                            phone_verified: verifications.phone_verified,
                            phone_verified_at: verifications.phone_verified_at,
                        }
                    })
                } catch (error) {
                    res.clearCookie("accessToken")
                    res.clearCookie("refreshToken")
                    return ResponseHandler.unauthorized(res, "unauthorized", "Invalid refresh token");
                }
            }

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.