Next.js Discord

Discord Forum

Refresh token without next-auth

Answered
Brown bear posted this in #help-forum
Open in Discord
Avatar
Brown bearOP
How can I implement access token refresh without using next-auth, with a custom backend? I need to set a cookie, and then use it on other pages to retrieve data for an authorized user, but I can't set cookies on a non-client component.
Answered by Korat
I find the only way IMO is the middleware
View full answer

6 Replies

Avatar
Korat
I find the only way IMO is the middleware
Answer
Avatar
Brown bearOP
I tried using middleware. As a result, when I attempted to retrieve the token from await cookies() in async pages, I received the token value from the previous page load.
Avatar
Korat
That could happen, I have an applyCookies function that might help ya, ill send you a bit later
Avatar
Brown bearOP
After countless attempts to write the correct middleware, I finally succeeded. I still can't notice any difference in the logic between the old and new code, but the new code works - and that's the main thing! Thank you for pointing me in the right direction!
Avatar
Korat
May I see your solution?

I dont think its cookies().set 😂
Avatar
Brown bearOP
middleware.ts
import { cookies } from "next/headers";
import { NextResponse } from "next/server";

export async function middleware() {
    const refreshTokenCookie = (await cookies()).get("refresh_token");

    const newResponse = NextResponse.next();

    if (refreshTokenCookie) {
        const response = await fetch(`http://localhost:8000/auth/refresh`, {
            method: "GET",
            headers: {
                Cookie: `${refreshTokenCookie.name}=${refreshTokenCookie.value}`
            },
            credentials: "include"
        });

        if (response.ok) {
            response.headers.getSetCookie().forEach(responseSetCookieStr => {
                const [cookieName, ...cookieValue] = responseSetCookieStr
                    .split(";")[0]
                    .split("=");
                newResponse.cookies.set(
                    cookieName.trim(),
                    cookieValue.join("=").trim(),
                    {
                        httpOnly: true
                    }
                );
            });
        }
    }

    return newResponse;
}

export const config = {
    matcher: ["/((?!api|_next/static|_next/image|favicon|.*\\.png$).*)"]
};