Next.js Discord

Discord Forum

Cookies get deleted after I perform this POST api request

Answered
Havana posted this in #help-forum
Open in Discord
HavanaOP
I use discord authentication oauth2 method, which basically returns to me the access + refresh tokens.
In the dev mode it worked perfectly fine for me, but in production it just stops working.
Each time I try and trigger that api endpoint and the return value differs from the previous one it insta deletes the access and refresh token cookies (at, rt).

This is how I store the cookies after I authenticated and it works perfectly fine:
    const response = NextResponse.json("http://localhost:3000/databases");

    const accessTokenCookie = serialize("at", accessToken, {
      httpOnly: true,
      secure: false,
      maxAge: 604800,
      sameSite: "strict",
      path: "/",
    });

    const refreshTokenCookie = serialize("rt", refreshToken, {
      httpOnly: true,
      secure: false,
      maxAge: tokenExpirySeconds,
      sameSite: "strict",
      path: "/",
    });

    response.headers.append("Set-Cookie", accessTokenCookie);
    response.headers.append("Set-Cookie", refreshTokenCookie);

    return response;


And this is the endpoint that screws the cookies:
import axios from "axios";
import { NextRequest, NextResponse } from "next/server";
import { RequestCookie } from "next/dist/compiled/@edge-runtime/cookies";
import db from "@/app/_utils/db";

export async function POST(req: NextRequest) {
  let body;
  try {
    body = await req.json();
  } catch (error) {
    return new NextResponse("Invalid request body", { status: 400 });
  }

  try {
    const {
      accessToken: accessTokenArgument,
      cookies: sentCookies,
    }: { accessToken: string; cookies: Record<string, RequestCookie> } = body;

    if (accessTokenArgument) {
      try {
        const UserData = (
          await axios.get("https://discord.com/api/users/@me", {
            headers: {
              Authorization: `Bearer ${accessTokenArgument}`,
            },
            withCredentials: true,
          })
        ).data;

        if (!UserData) {
          return new NextResponse("Failed to retrieve user's data", {
            status: 401,
          });
        }

        return NextResponse.json({ UserData }, { status: 200 });
      } catch (error) {
        return new NextResponse("Error retrieving user data", { status: 500 });
      }
    }
    let accessToken = sentCookies?.at?.value;

    if (!accessToken) {
      return NextResponse.json("No AT", { status: 500 });
    }
    try {
      const response = await axios.get("https://discord.com/api/users/@me", {
        headers: { Authorization: `Bearer ${accessToken}` },
        withCredentials: true,
      });

      const roles = await db.roles.findMany({
        where: { user_id: response.data.id },
        select: { role_name: true, color: true },
      });

      const { id, global_name, avatar } = response.data;

      const user = await db.users.findFirst({ where: { uid: id } });

      if (user) {
        await db.users.update({
          where: { uid: id },
          data: { username: global_name, avatar },
        });
      }

      const res = NextResponse.json(
        {
          UserData: response.data,
          roles,
          userPremium: user?.issubscribed,
        },
        { status: 200 }
      );

      return res;
    } catch (error) {
      return new NextResponse("Internal Server Error", { status: 500 });
    }
  } catch (err) {
    return new NextResponse("Internal Server Error", { status: 500 });
  }
}
Answered by "use php"
So you gave me access to the source.

And here is what I found:
- You had a link component in navbar
- That Link component was prefetching /logout
- that resulted in a logout
View full answer

22 Replies

HavanaOP
Those are the server actions that trigger this POST request, I tried using the original function without caching, and it still didn't work:
import axios from "axios";
import { cache } from "../../_helpers/cache";
import {
  RequestCookie,
  RequestCookies,
} from "next/dist/compiled/@edge-runtime/cookies";
import { cookies } from "next/headers";

const emptyUser: Partial<Me> = {
  id: "",
  global_name: "",
  avatar: "",
  username: "",
};

export const getUserData = async (cookies?: Record<string, RequestCookie>) => {
  try {
    const response = await axios.post(
      "http://localhost:3000/api/discord/getuserdata",
      { cookies },
      { withCredentials: true }
    );
    console.log(response.data);
    return response.data;
  } catch (error) {
    return { UserData: emptyUser, roles: [], userPremium: false };
  }
};

export const getUserDataCached = async (
  cookies?: Record<string, RequestCookie>
) => {
  const data = await getUserData(cookies);
  const userId = data.UserData.id || "default";
  return cache(() => getUserData(cookies), [`userData_${userId}`], {
    revalidate: 60 * 60 * 20,
    tags: ["userData"],
  });
};

export const getUserDataProcess = async (
  cookiesSent?: RequestCookies
): Promise<{
  data: {
    UserData: Me;
    roles: { role_name: string; color: string }[];
    userPremium: boolean;
  };
}> => {
  const cookieStore = cookies();
  const cookiesToUse = cookiesSent ?? cookieStore;
  const cookieHeaders = Object.fromEntries(cookiesToUse);
  const data = await getUserDataCached(cookieHeaders);
  return { data };
};
I am using next 15 if it helps somehow, basically means that all routes are dynamic by default
Havana
@Havana aint NO ONE know the answer to your issue
HavanaOP
:sadness:
Havana
$5 to whoever solves this
Havana
@Paper wasp
@Havana
why do cookies get deleted in prod but not dev
Havana
@Multiflora rose seed chalcid
fix this I beg
@Havana <:sadness:1084117564717809855>
Blue swimming crab
hi, there.
i wanna ask you why you set { httpOnly: true}
@Blue swimming crab i wanna ask you why you set { httpOnly: true}
That means the client script can’t access it
@Blue swimming crab i wanna ask you why you set { httpOnly: true}
HavanaOP
for security, it doesnt make the bug occur
@Havana for security, it doesnt make the bug occur
Blue swimming crab
did you try to make it false?
@Blue swimming crab did you try to make it false?
HavanaOP
yes
same shit
I found the rarest bug I guess, its not about setting cookies, its about how I access them maybe
So you gave me access to the source.

And here is what I found:
- You had a link component in navbar
- That Link component was prefetching /logout
- that resulted in a logout
Answer