How to clear cookie in NextJs 13 using app router?

My NextJs application is using app router. I am currently building an admin application and i want to clear the cookie when tab close is detected. How can i achieve that? I am new to nextjs and it is using cookie to authenticate. I am using axios to fetch my external backend server. The accessToken from my backend api gets expired in 1hr and i have set the MAX_AGE of the jwt session token to 1hr. I also want to logout automatically when the token expires. how can achieve this all?

This is how my layout.tsx file looks like

import React, { FC } from "react";
import ThemeRegistry from "@/theme/ThemeRegistry";
import { Poppins } from "next/font/google";
import ReduxProvider from "@/store/provider/ReduxProvider";
import "./globals.css";
import AuthProvider from "@/context/AuthProvider";

const poppins = Poppins({ subsets: ["latin"], weight: "400" });

interface LayoutProps {
  children: React.ReactNode;
  types: string;
}

export const metadata = {
  title: "VastuVilla",
  description: "Comprehensive Household Services",
};

const RootLayout: FC<LayoutProps> = async ({ children, types }) => {
  return (
    <html lang="en" className="bg-white">
      <AuthProvider>
        <ReduxProvider>
          <ThemeRegistry>
            <body className={poppins.className}>{children}</body>
          </ThemeRegistry>
        </ReduxProvider>
      </AuthProvider>
    </html>
  );
};

export default RootLayout;

and this is my page.tsx file

import React from "react";
import { NextPage } from "next";
import { redirect } from "next/navigation";
import { getServerSession } from "next-auth/next";
import { options } from "./api/auth/[...nextauth]/options";

const Home: NextPage = async () => {
  const session = await getServerSession(options);
  if (!session) {
    redirect("/login");
  }

  return (
    <main className="main" data-testid="home-component">
      Hello
    </main>
  );
};

export default Home;

this is my middleware.ts file

import { NextRequest, NextResponse } from "next/server";
import { getErrorResponse } from "./lib/helpers";

let redirectToLogin = false;
export async function middleware(req: NextRequest) {
  let token: string | undefined;

  if (req.cookies.has("next-auth.session-token")) {
    token = req.cookies.get("next-auth.session-token")?.value;
  } else if (req.headers.get("Authorization")?.startsWith("Bearer ")) {
    token = req.headers.get("Authorization")?.substring(7);
  }

  if (req.nextUrl.pathname.startsWith("/login") && (!token || redirectToLogin))
    return;

  if (req.nextUrl.pathname.startsWith("/signup") && (!token || redirectToLogin))
    return;

  if (
    !token &&
    (req.nextUrl.pathname.startsWith("/api/users") ||
      req.nextUrl.pathname.startsWith("/api/auth/logout"))
  ) {
    return getErrorResponse(
      401,
      "You are not logged in. Please provide a token to gain access."
    );
  }

  const response = NextResponse.next();

  if (!token) {
    return NextResponse.redirect(new URL(`/login`, req.url));
  }

  if (req.url.includes("/login") && token) {
    return NextResponse.redirect(new URL("/", req.url));
  }

  if (req.url.includes("/signup") && token) {
    return NextResponse.redirect(new URL("/", req.url));
  }

  return response;
}

export const config = {
  matcher: [
    "/profile",
    "/login",
    "/signup",
    "/api/users/:path*",
    "/api/auth/logout",
  ],
};

and this is my api to authenticate

import { __RUNTIME_CONFIG__ } from "@/config";
import { __REACT_APP_AUTHENTICATION__ } from "@/config/apiConfig";
import axiosInstance from "@/services/axiosFactory/axiosInstance";
import type { NextAuthOptions } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import FacebookProvider from "next-auth/providers/facebook";
import GoogleProvider from "next-auth/providers/google";

export const options: NextAuthOptions = {
  pages: {
    signIn: "/login",
  },
  session: {
    strategy: "jwt",
    maxAge: 1 * 60 * 60,
  },
  providers: [
    FacebookProvider({
      clientId: __RUNTIME_CONFIG__.FACEBOOK_ID as string,
      clientSecret: __RUNTIME_CONFIG__.FACEBOOK_SECRET as string,
    }),
    GoogleProvider({
      clientId: __RUNTIME_CONFIG__.GOOGLE_CLIENT_ID as string,
      clientSecret: __RUNTIME_CONFIG__.GOOGLE_CLIENT_SECRET as string,
    }),
    CredentialsProvider({
      name: "Credentials",
      credentials: {
        username: {
          label: "Username:",
          type: "text",
          placeholder: "your-cool-username",
        },
        password: {
          label: "Password:",
          type: "password",
          placeholder: "your-awesome-password",
        },
        email: {
          label: "Email:",
          type: "email",
          placeholder: "your-email",
        },
      },
      async authorize(credentials) {
        const response = await axiosInstance.post(
          __REACT_APP_AUTHENTICATION__.AUTHENTICATE_SERVICE,
          {
            email: credentials?.email,
            loginName: credentials?.username || "",
            password: credentials?.password,
          }
        );
        const user = response.data;
        if (user) {
          axiosInstance.defaults.headers.common["Authorization"] =
            "Bearer " + user.accessToken;
          return user;
        } else {
          return null;
        }
      },
    }),
  ],
  callbacks: {
    async jwt({ token, user, session }) {
      if (user) {
        return {
          ...token,
          ...user,
        };
      }
      return token;
    },
    async session({ session, token, user }) {
      return {
        ...session,
        user: {
          ...session.user,
          accessToken: token.accessToken,
          iat: token.iat,
          exp: token.exp,
          jti: token.jti,
        },
      };
    },
  },
  secret: __RUNTIME_CONFIG__.NEXTAUTH_SECRET,
  debug: process.env.NODE_ENV === "development",
};

Leave a Comment