Refresh auth token in nextjs 13 with custom backend

22 views Asked by At

I'm struggling with refreshing the access token. I have a custom BE (in Django) which handles authentication but in the FE, since I can only update cookies on server actions or route handlers.

When I log in, I store the cookies like this, in a server action under actions/auth:

const setSessionCookies = (session: UserState) => {
  const sessionString = JSON.stringify(session);

  cookies().set('session', sessionString, {
    expires: new Date(session.refresh_expiration || ''),
    httpOnly: true,
  });
};

export const signIn = async (email: string, password: string): Promise<UserState>=> {
  const { data } = await signInService(email, password);
  setSessionCookies(data);
  return data;
};

To refresh the token I have the following server action:

export const refreshToken = async () => {
  const currentSessionCookies = cookies().get('session')?.value;
  if (currentSessionCookies) {
    const currentSession: UserState = JSON.parse(currentSessionCookies);
    const { data } = await refreshTokenService(currentSession.refresh || '');
    if (data) {
      currentSession.access = data.access;
      currentSession.access_expiration = data.access_expiration;
      setSessionCookies(currentSession);
      return data;
    }
  }
};

I have tried it in three ways:

  1. Creating a middleware.ts file, but I get the error that says cookies can't be set outside of server actions or route handlers:
export async function middleware(request: NextRequest) {
  const sessionCookie = cookies().get('session')?.value;

  if (sessionCookie) {
    const session: UserState = JSON.parse(sessionCookie);
    if (session.refresh_expiration && new Date(session.refresh_expiration).getTime() <= Date.now()) {
      await signOut();
      return NextResponse.redirect(new URL('/', request.url));
    } else if (session.access_expiration && new Date(session.access_expiration).getTime() <= Date.now()) {
      await refreshToken();
      return NextResponse.next();
    }
  }
  return NextResponse.next();
}
  1. Creating an interceptor with axios to handle it in the same way as the middleware, but get the same error: api.interceptors.request.use(...);
  2. Creating an api route: api/auth/refresh to try updating it from there, but in this case the cookies are empty when I do cookies().getAll(), so not sure how to update it there.

Any thoughts? I've placed 'use server' at the top of actions/auth to make sure those are server actions, but when called from middleware or axios interceptor, it seems i can't update the cookies.

0

There are 0 answers