Search code examples
reactjsnext.jscookiesroutesmiddleware

deleting cookies and user redirection with next.js 13 does not work


I'm creating a course platform, where a user, when registering on the application, receives a token that is stored in cookies, after 24 hours the token expires, and I want to delete the cookie, and redirect the user to the /login page, but I don't understand, request.cookie even says it deletes it, but it doesn't delete it from the browser, I used response.cookie.delete(), and it worked and I deleted it from the browser, but I have to give a return response for the deletion to work, because in the javascript I can't use anything below the return, I don't know how to redirect the user, and the return is read correctly and deletes the cookie and redirects him to log in again, I'm using middleware so I don't repeat code in all private routes, code below:

src/middleware.ts

import { NextResponse, type NextRequest } from 'next/server'

export async function middleware(request: NextRequest) {
  const cookie = request.cookies.get("token")?.value!
  const res = NextResponse.next()

  const response = await fetch(`${request.nextUrl.origin}/api/verifycookie`, {
    method: "POST",
    headers: {
      cookies: cookie
    }
  })
  const data = await response.json()

  if(data.ExpiredToken){
    res.cookies.delete("token")
    return res
  }else if(data.error){
    return NextResponse.redirect(new URL("/signIn", request.url))
  }
}
export const config = {
  matcher: ["/home", "/cart", "/contact", "/exploreCourses", "/plains"]
}

code of the route verifyCookie below:

import { NextRequest, NextResponse } from "next/server";

export async function POST(request: NextRequest){
    const cookieValue = request.headers.get("cookies")
    const url = process.env.URL

    const response = await fetch(`${url}/verifyExpToken`, {
        method: "POST",
        headers: {
            "Authorization": `Bearer ${cookieValue}`
        }
    })
    const data = await response.json()

    if(data.error == "Token Expirado"){
        return NextResponse.json({ExpiredToken: "Token Expirado"}, {status: 403})
    }else if(data.error){
        return NextResponse.json({error: data.error}, {status: 401})
    }

    return NextResponse.json({success: "Token válido"}, {status: 200})
}

My question is, how can I actually delete the cookie, and redirect the user to /login? I tried different ways, and I couldn't

I've already tried to delete the cookies using request.cookies.delete, I expected it to delete them completely, both from the request and from the browser, but it doesn't delete them from the browser, and remains in devtools in the application tab, I tried creating a separate function with return NextResponse .redirect, and call the function outside, as there are two returns in different scope, and it didn't work either. But not working


Solution

  • I managed to solve my problem, I used the library precisely for next.js, cookies-next, it serves the basic concepts of next js, it works in both client and server components, middleware, routehandler, server actions, etc.. ., as long as you pass the correct parameters, as I wanted to delete the cookie and redirect the user, my code is below:

    import { deleteCookie } from 'cookies-next';
    import { NextResponse, type NextRequest } from 'next/server'
    
    export async function middleware(req: NextRequest) {
      const cookie = req.cookies.get("token")?.value!
      const res = NextResponse.next();
      const url = process.env.URL
    
      const response = await fetch(`${url}/verifyExpToken`, {
        method: "POST",
        headers: {
          "Authorization": `Bearer ${cookie}`
        }
      })
      const data = await response.json()
    
      if(data.status == 403){ //token expirado
        deleteCookie('token', { res, req });
        return NextResponse.redirect(new URL("/login", req.url))
      }else if(data.error){//erros como: token invalido, modificado, ou não assinado
        deleteCookie('token', { res, req });
        return NextResponse.redirect(new URL("/signIn", req.url))
      }
      return res
    }
    export const config = {
      matcher: ["/home", "/cart", "/contact", "/exploreCourses", "/plains"]
    }
    

    notice that I passed the res and req as parameters of the deleteCookie function, read more about cookies-next here to know what to pass and when to use it in each case: https://www.npmjs.com/package/cookies-next.