The issue with the Nextjs build is stemming from problems related to jsonwebtoken in the _middleware

I need some assistance with deploying on Vercel. I have created a _middleware.ts file that checks for a JWT in the user's cookie.

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

export async function middleware(req: NextRequest) {
  let response = NextResponse.next()
  const url = req.nextUrl.clone()

  const token = req.cookies['allow-list']

  if (!token || token === 'deleted') {
    return response 
  }

  try {
    const decodedToken = verify(
      token,
      process.env.TOKEN_SECRET as string
    ) as JwtPayload
  } catch (e) {}

  return response
}

However, when I attempt to build my project, I encounter the error: "Dynamic Code Evaluation (e. g. 'eval', 'new Function') not allowed in Middleware pages/_middleware". Is there a solution to this issue? It functions properly when running locally.

[22:59:29.409] Cloning github.com/dimitriborgers/test (Branch: master, Commit: efc1977)
[22:59:30.051] Cloning completed: 642.161ms
[22:59:30.427] Installing build runtime...
[22:59:34.350] Build runtime installed: 3.924s
[22:59:35.048] Looking up build cache...

(remaining content paraphrased for uniqueness)

Answer №1

Due to the browser-based nature of the middleware runtime, using eval in that context is restricted. Additionally, the maximum allowed duration for the middleware runtime is limited to 1.5 seconds, making it impossible to fetch verification from another server via an Edge Function.

To address this constraint, I decided to eliminate the dependency on the jsonwebtoken library and instead utilized jose to streamline the codebase. This adjustment ensures compatibility with both browser and server runtimes, allowing us to verify users directly at the middleware level.

Generating a Signed JWT

import * as jose from 'jose';

const jwtToken = await new jose.SignJWT({ userId: `your-data` })
                        .setProtectedHeader({ alg: 'HS256' })
                        .setIssuedAt()
                        .setExpirationTime('30d')
                        .sign(new TextEncoder().encode(`secret-key-phrase`));

Verifying the JWT

This method functions smoothly within the middleware environment (Edge Function on Vercel).

import * as jose from 'jose';

try {
    const { payload: jwtData } = await jose.jwtVerify(
        jwtToken, new TextEncoder().encode(`secret-key-phrase`)
    );
    // jwtData.uid => `your-data`
} catch (error) {
    console.log(error);
    // The JWT validation has failed or the token is invalid
}

Answer №2

Many of the core nodejs APIs are not compatible

edge runtime

This is an official example from next js: source code for jwt middleware. The code example utilizes jose from jose repository

import { type NextRequest, NextResponse } from 'next/server'
import { verifyAuth } from '@lib/auth'

export const config = {
  matcher: [ '/api/protected', '/protected' ],
}

export async function middleware(req: NextRequest) {
  // ensuring user authentication
  const verifiedToken = await verifyAuth(req).catch((err) => {
    console.error(err.message)
  })

  if (!verifiedToken) {
    // JSON response for API requests
    if (req.nextUrl.pathname.startsWith('/api/')) {
      return new NextResponse(
        JSON.stringify({ 'error': { message: 'authentication required' } }),
        { status: 401 });
    }
    // redirect to the set token page
    else {
      return NextResponse.redirect(new URL('/', req.url))
    }
  }
}

Answer №3

If you wish to retain the use of jsonwebtoken, here is an alternative solution that you can implement within your middleware file.

export const config = {
     runtime: "edge",
     unstable_allowDynamic: [
         '**/node_modules/lodash/**/*.js',
    ],
 };

You should also include any other packages that make use of eval. The current version of jsonwebtoken when using decode should resolve the issue. If you are utilizing verify, additional libraries may need to be added to the unstable_allowDynamic.

However, it is worth noting that the preferred solution, as suggested by others, would likely involve transitioning to different libraries altogether.

Answer №4

The @tsndr/cloudflare-worker-jwt library is a great alternative to using jsonwebtoken.

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

Inspecting a substring of an element dynamically added in VueJs

When I click a button in my form, it adds a new line. The challenge is making sure that each new line evaluates independently and correctly. In this case, the task involves checking the first 2 digits of a barcode against a dataset to determine a match or ...

Utilize the latest REDUX state within a React component's function

I'm currently facing an issue in my React application where I am struggling to access the updated state from within a function. Here is a simplified version of my problem: I have a custom React Component to which I pass a variable representing the st ...

Unable to access account: HTML Javascript login issue

Problem with Login Code As a newcomer to HTML, CSS, and almost unknown in Javascript, I sought help from others to create a login code. The code was working fine earlier, but now it's not functioning as expected. Despite checking everything, I can&ap ...

Skipping MongoDB in loop operations in a Node.js environment.The original text was modified to

Apologies for the beginner question (The following code is related to express framework and mongoose DB) I am attempting to iterate through the array 'Users' which contains usernames. Then, I am trying to match them in the mongoose database to r ...

Explore the input from multiple users to uncover the word that appears most frequently among them

Hey there (brand new to JavaScript), I am working on a simple program that requires input from multiple users through prompt pop-ups. For example: <script type="text/javascript> var userInput = prompt("Enter your input:"); </script> It&ap ...

Update the path dynamically in Next.js without the need to reload the page

Every time the user clicks on the continue button, a function is triggered. Within that function, I make the following call: push("/signup/page-2", undefined, { shallow: true }); All dynamic routes resembling /signup/[page].js that return <Component / ...

Manipulate the color of the parent text using a button nested within

I am working on a script that adds a button to div elements with the class name "colors". When the button is clicked, the text color of the parent element will change to a specified color. However, I'm facing an issue where it only changes the last el ...

Overlaying images on top of text

Is there a way to overlay an image on text, like a pattern image? Similar to applying color with a hex value in CSS: color: #ffffff; Any ideas on how this can be achieved? I want to have a pattern over text. https://i.sstatic.net/JaNZU.jpg Appreciate ...

Adding a DOM element within a React component

In my project, I am using Django for both the backend and most of the frontend, with the exception of one form that is built in ReactJS. To improve the loading speed of this specific form, I want to fetch its data directly from the HTML instead of making a ...

Differences between `component` and `render` in React Router routes

Two questions have arisen for me when using Route from react-router-dom(v4.3.1): What is the difference between using component and render in Route: <Route exact path='/u/:username/' component={ProfileComponent} /> <Route exact path ...

Issues with anchor tag click event in Firefox browser not functioning as expected

I have encountered an issue while trying to create an anchor tag in a TypeScript file. When clicking on this button, the anchor tag should be created. This functionality is working correctly in Chrome and IE, however, it seems to be not working in Firefo ...

Ways to showcase title using ng-repeat

<input type="text" ng-model= "name" title="{{name}}">//this title displays the name that is contained in ng-model Similarly... <select title ="{{item.actionId}}" ng-model="item.actionId"> <option ng-repeat="action in actionList" value="{{ ...

What is the process for appending a value to an array of JSON objects?

I have a JSON array containing objects which I need to pass the values to the DataTables. [{ _id: '58a2b5941a9dfe3537aad540', Country: 'India', State: 'Andhra Pradesh', District: 'Guntur', Division: ...

Tips for identifying screen orientation in a mobile website using React JS and the orientationchange event

I am working on detecting screen orientation changes using the event orientationchange, which is supported by all major mobile browsers. In order to achieve this, I have added an event listener in the componentDidMount method and updating the state inside ...

Utilizing factory service within a decorator in AngularJS

Utilizing the TextAngular plugin and attempting to customize a toolbar, I am striving to inject my own service (LinkService) into the module but encountering an [$injector:unpr] Unknown provider issue. module.config(function($provide, LinkService){ $p ...

Unable to retrieve the HTML value attribute that contains a double quotation mark

Here is an example of my HTML attribute: <span> <input class="editWidgetName" type="text" maxlength="100" value="Untitled "NAME" 30\10\2017" style="display:none;padding-right:1px;" /> </span> Despi ...

What is the best way to have text automatically selected upon clicking a category in a combobox? (Vue.JS 2)

I am currently working with a Vue component that looks like this: <script> export default{ template: '\ <select class="form-control" v-model="selected" v-on:change="search">\ <option v- ...

looking to save a service or factory as a variable

I seem to be at a standstill when it comes to finding a solution for my mvc.NET / angularjs project. So far, I believe I've done a good job abstracting the view to use a controller that matches the type name of the specific controller.cs class: < ...

Page rendering issue: Could not load script: /_next/static/chunks/pages/_error-2280fa386d040b66.js

Check out this image of the static directory After successfully running this website locally, I deployed it to Heroku. However, I encountered an issue where it would only load halfway and then go blank. The Chrome console kept showing errors that I haven ...

"The Vue component's data is successfully updating within a method using setInterval(), however, the changes are not reflected in the DOM

I have a function in my methods that gets triggered with a @click in the view. The function starts a timer, and although it seems to work fine in the DevTools, the timer only updates in the DevTools when I refresh the page. Moreover, in the view, the time ...