Setting cookies with NextJS Route API post middleware

@ Using NextJS 13.3 with App Dir and API Routes.

I am currently working on implementing an authentication system using NextJS with my external NodeJS backend. The process involves the frontend sending credentials to the backend, which validates them and returns an accessToken and refreshToken. NextJS then creates a new JWT and encodes the user information, token, and refreshToken received from the backend.

For session validation, the middleware fetches the API route in NextJS, decodes the JWT to check if the accessToken from the backend is valid. If it has expired, the middleware attempts to refresh a new accessToken using the refreshToken. Once the new accessToken is received, the API sets the cookies and returns success=true. If the success is true, the middleware proceeds; if false, it redirects to the login page.

While this setup is functioning smoothly, there is a problem that needs addressing. When the backend sends the new accessToken to NextJS, the nextjs API sets the cookies, but it appears that the cookies are set only after the middleware response. As a result, when a user visits the page after refreshing the token, they encounter a forbidden error because the old cookie is still in use. A subsequent page refresh brings the new cookies along.

I would appreciate any assistance in resolving this issue and identifying where I might be going wrong.

Middleware:

import { NextResponse } from 'next/server';
import conf from '@/config/conf';

export async function middleware(request) {
  const accessToken = request.cookies.get('accessToken')?.value;

  const verifySessionResponse = await fetch(`${conf.BASE_URL}/proxy/auth/verify-session`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ accessToken: accessToken })
  });

  const json = await verifySessionResponse.json();

  if (!json.success) {
    return NextResponse.rewrite(new URL('/auth/login', request.url))
  }

  return NextResponse.next(verifySessionResponse);

}

export const config = {  
  matcher: '/dashboard/:path*'
}

Route API:


import conf from '@/config/conf';
import jwt from 'jsonwebtoken';

export async function POST(request) {  
    const { accessToken } = await request.json(); 
    // Rest of the code...
}

I have exhausted all my options and efforts. All I want is for the API to set the cookies after receiving the new token and then continue uninterrupted.

Answer №1

If you want to create a new instance of the NextResponse class and configure cookies, it can be easily done. Check out this snippet showcasing how I implement the response function:

export function handleResponse(data: object, statusCode = 200): any {
  let cookies = undefined;

  if (typeof data == 'object' && 'cookies' in data) {
    cookies = data.cookies;
    delete data.cookies;
  }

  let responseBody = '';
  try {
    responseBody = JSON.stringify(data);
  } catch (error) {
    responseBody = JSON.stringify(ErrorHandler(error, __filename, 500, false));
  }

  const customResponse = new NextResponse(responseBody, {
    status: statusCode, // Customize your desired status code here
    headers: {
      'Content-Type': 'application/json', // Define content type if necessary
    },
  });

  if (Array.isArray(cookies)) {
    for (const cookie of cookies) {
      customResponse.cookies.set(cookie);
    }
  } else {
    cookies && customResponse.cookies.set(cookies as any);
  }

  return customResponse;
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there any way to extract the source files from a compiled Electron application?

Is there a way to extract the contents of a .app Application developed using Electron for Mac OS? I'm eager to explore the underlying source files, but I'm not familiar with the procedure to access them. Any assistance would be greatly appreciate ...

Is there a way to deactivate the <script> tag using CSS specifically for media queries?

When designing a website exclusively for desktop usage, I encountered the issue of it not being viewable on mobile devices. I attempted to address this problem by utilizing the code below: script { display: none; pointer-events: none; } Unfortunat ...

Troubleshooting the Hover Effect of Buttons in Next.js when Using Tailwind CSS for Dynamic Color Changes

Encountering a problem with button hover functionality in a Next.js component using Tailwind CSS. The objective is to alter the button's background color dynamically on hover based on a color value stored in the component's state. This code func ...

Emulate an AngularJS ng-click action

My website has HTML code with three buttons: <button ng-click='showStats(player.data,0)'>Death Match</button> <button ng-click='showStats(player.data,1)'>Champions Rumble</button> <button ng-click='sho ...

I keep encountering the following error message: " ERROR Error Code: 200 Message: Http failure during parsing for http://localhost:3000/login"

My Angular Login component is responsible for passing form data to the OnSubmit method. The goal is to send form data from the front-end application and authenticate users based on matching usernames and passwords in a MySQL database. ***This login form i ...

Prevent useSWR from saving any alterations made to the fetched data

It seems like I'm having some trouble understanding how to properly use useSWR with React. Let me explain the issue in a simpler way: I am fetching data using useSWR and then changing the title of this object. The problem arises when navigating back ...

The curly braces in AngularJS are not resolving as expected, however, the ng-bind directive is functioning properly

I'm currently working on a Django application and utilizing AngularJS for my frontend. I have a straightforward piece of code that looks like this: <div class="vert-carousel" ng-controller="PrizeController"> <div class="gallery-cell" n ...

CORS headers present but AJAX request still fails

A request sent via AJAX from a locally hosted page to a remote server is encountering errors, despite the presence of CORS headers. The JavaScript code for this request is as follows: $.ajax({url: 'http://prox.tum.lt/420663719182/test-upload?Action=S ...

Dealing with soon-to-expire access tokens from a partner API

Just starting out with Next.js and facing a common challenge without knowing where to begin. Here's the scenario: I am working with a partner who has an API that requires Bearer authentication. The Bearer token is obtained by calling an endpoint (/au ...

How can private data be shown on a multiplayer HTML5 canvas game using socketIO in a Node/Express server?

One challenge I've encountered while working on my online canvas game using Node/Express and socketIO is the ability to display private data for individual players. So far, everything has been smooth sailing when it comes to displaying public informat ...

What is a more effective method for updating a component by utilizing both state and props for rendering?

I am new to Next.js and ReactJS, and I recently encountered a situation where I needed to create a component that would render different child components within the parent component based on a click event in the DOM element to change its state. My initial ...

Having trouble reaching the io object in session.socket.io

I have integrated session.socket.io into my application. o = require('socket.io').listen(tmpServer), appCookieParser = express.cookieParser(settings.cookie.secret), appRedisStore = new RedisStore(), sessionIO = new SessionSockets(io, appRedisSto ...

Altering the context of Javascript script execution

I needed to switch the JavaScript execution context from the parent window to the child window. I was able to successfully load my script objects and functions into the child window context, however, I encountered difficulty in making third party libraries ...

Having trouble sending JSON data to the server using a POST request

I am encountering an issue while attempting to send JSON data to the server using the fetch API and PHP as the server-side language. The PHP code on the server side is quite simple: <?php header("Access-Control-Allow-Origin: *"); header("Access ...

Is there a way to specifically clear the cached view for a single file in express.js?

When I render my homepage using the following code: router.get('/', function(req, res, next) { res.render('../_cache/homepage-1.hbs', { title: 'Home', style: 'home-new', projectSlug: &apo ...

Is there a way to modify the button's color upon clicking in a React application?

I am a beginner in the world of React and currently exploring how to utilize the useState hook to dynamically change the color of a button upon clicking. Can someone kindly guide me through the process? Below is my current code snippet: import { Button } ...

Tips on implementing multiple consecutive setState calls in ReactJS

Recently, I discovered that setState is an async call. I'm facing an issue where I need to utilize the updated result from setState immediately after setting it, but due to its async nature, I end up getting the old state value. While researching for ...

Stopping JavaScript when scrolling to the top and running it only when not at the top

I found a great jQuery plugin for rotating quotes: http://tympanus.net/codrops/2013/03/29/quotes-rotator/ Check out this JSFiddle example: http://jsfiddle.net/LmuR7/ Here are my custom settings (with additional options that I haven't figured out yet) ...

Using jQuery's toggle function with a double click event to change the display to none

A div I created has the ability to expand to full screen upon double click, and I now wish to implement a toggle function so it can return to its original size when double clicked again. Initially, the code successfully increased the size of the div. Howe ...

Struggling with loading.jsx file in next js version 13.4.5?

Encountered an issue with loading components in next js 13.4.5 layout.jsx "use client"; import React, { Suspense } from "react"; import { ThemeProvider, createTheme } from "@mui/material/styles"; import CssBaseline from " ...