Secure your API routes in NextJS by using Passport: req.user is not defined

Currently, I am utilizing NextJS for server-side rendering and looking to secure certain "admin" pages where CRUD operations on my DB can be performed.

After successfully implementing authentication on my website using passport and next-connect based on a tutorial from here, I now want to prevent any unauthorized "edit" operations.

I believe the most effective way to achieve this is by checking if req.user exists in my /page/API files, but it's not functioning as expected. At present, req.user returns undefined, despite the cookie being stored on my device after successful login.

I have encountered similar issues on Stackoverflow, albeit few related to Nextjs, and none of them provided a solution that worked for me, possibly due to my limited experience in JS and authentication.

Upon logging in through the auth API, req.user exists and the cookie is successfully stored:

/pages/api/auth

req.user => OK

import nextConnect from 'next-connect';
import middleware from '../../middleware/middleware';
import passport from '../../lib/passport';
import { extractUser } from '../../lib/api-helpers';

const handler = nextConnect();
handler.use(middleware);

handler.post(passport.authenticate('local'), (req, res) => {
  res.json({ user: extractUser(req.user) });
  console.log(req.user) // IT WORKS
});

export default handler;

However, when logged in and fetching data through any API, req.user is returned as undefined.

An example of one of my API file:

/page/api/getList.js

import nextConnect from 'next-connect';
import middleware from '../../middleware/middleware';

const handler = nextConnect();
handler.use(middleware);

handler.post(async (req, res) => {

  console.log(req.user) // UNDEFINED

  // operation to perform if req.user exists
  
});

export default handler;

If necessary, here are snippets of my session middleware :

middleware/session.js

import session from 'express-session';
import connectMongo from 'connect-mongo';
import * as uuid from 'uuid';

const MongoStore = connectMongo(session);

export default function sessionMiddleware(req, res, next) {
  const mongoStore = new MongoStore({
    client: req.dbClient,
    stringify: false,
  });
  return session({
    secret: "this gonna rocks !",
    store: mongoStore,
    resave: true,
    saveUninitialized: true,
    cookie: {
      maxAge: (1000 * 60 * 100)
    }
  })(req, res, next);
}

and my common middleware :

import nextConnect from 'next-connect';
import passport from 'passport';
import database from './database';
import session from './session';

const middleware = nextConnect();

middleware
  .use(database)
  .use(session)
  .use(passport.initialize()) // passport middleware handles authentication, populating req.user
  .use(passport.session());

export default middleware;

I'm unsure where I might be going wrong. Can someone guide me on how to verify user authentication before performing any DB operation?

Many thanks!

Answer №1

Dealing with a similar issue led me to discover the following solution:

  1. Create a middleware function that returns the handler when it encounters an error or response. For example:

    const middleware = (handler) => async (req, res) =>{
    
    //Middleware function logic here
    //Code execution
    
    return (res.send(data), handler(req, res));
    
    //Error handling
    
    return res.send("error"), handler(req, res)
    
    }
    
  2. In your handler file or API file:

    const handler = (req, res)=>{
    // Your code implementation here
    }
    
    // How to export multiple middlewares    
    export default connectToMongo(middleware(handler));
    
  3. Ensure that you export middleware() inside connectToMongo(). This sequence ensures establishing a database connection first, followed by middleware checks, and eventually executing the handler.

  4. Avoid establishing a connection in the middleware function. Instead, create a separate function and incorporate it in your API. Remember to pass it within the connectToMongo() function for connection setup.

I have attempted to simplify the explanation in hopes of aiding you. If further assistance is needed, please inform me.

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

Utilizing Visual Studio: Implementing jsmin in post-build actions

After attempting to add jsmin.exe as a post-build event in my VS 2010 project, I encountered an "error code 9009" when building the project. I tested this in the command prompt and found that it works if I navigate to the folder and run: jsmin < debug ...

Converting keyValue format into an Array in Angular using Typescript

Is there a way to change the key-value pair format into an array? I have received data in the following format and need to convert it into an array within a .TS file. countryNew: { IN: 159201 BD: 82500 PK: 14237 UA: 486 RU: 9825 } This needs to be transf ...

Transform a flat 2D shape into a dynamic 3D projection using d3.js, then customize the height based on the specific value from ANG

Currently, I am utilizing d3.js version 6 to generate a 3D representation of the 2D chart shown below. Within this circle are numerous squares, each colored based on its assigned value. The intensity of the color increases with higher values. https://i.ss ...

The appropriate method for transferring a prototype to an object

From my perspective, prototypes work like this: let Animal = function() { this.bark = "woof"; } Animal.prototype.barkLoud = function() { return this.bark.toUpperCase(); } let x = new Animal(); x.barkLoud() = "WOOF"; I f ...

Unable to integrate NextJS with Firebase

I have been working on creating an app using Firebase and NextJS, but so far all my attempts have been unsuccessful. Below is a detailed account of my latest attempt. Hopefully, someone can help point out where I may be going wrong. Here is the sequence ...

Capture input before onChange and ideally only accept numerical values

Preparing for inexperienced users, I have a table of input fields. My goal is to enhance user experience and make the form as user-friendly as possible. I have developed code that highlights the table row immediately after an input field has changed. Howe ...

Saving a PHP form with multiple entries automatically and storing it in a mysqli database using Ajax

My form includes multiple tabs, each containing various items such as textboxes, radio buttons, and drop-down boxes. I need to save the content either after 15 seconds of idle time or when the user clicks on the submit button. All tab content will be saved ...

The success function is failing to display the Ajax response

Is there a way to correctly display the ajax response of my code? I noticed that when using async=true, only the last value of yy is shown. However, I want to display it for all values from 0 to a. Interestingly, everything works fine when using async=fa ...

Switching between API requests through a live feed

Hey there: import Rx from 'rxjs'; function mockApi(endpoint, time, response) { return new Rx.Observable(observer => { console.log(`${endpoint}: Request initiated.`) let active = true; const id = setTimeout(() => { cons ...

Is it possible to integrate jQuery and JavaScript together?

Can I combine JavaScript selector document.querySelector with jQuery functions instead of using $ or jQuery selectors? For instance: $.getJSON("list.json", function(data) { document.querySelector("#content").html(data.name); }); When trying to use d ...

Alternative solution to avoid conflicts with variable names in JavaScript, besides using an iframe

I am currently using the Classy library for object-oriented programming in JavaScript. In my code, I have implemented a class that handles canvas operations on a specific DIV element. However, due to some difficulties in certain parts of the code, I had t ...

What steps should I take to resolve the error: Uncaught SyntaxError: expected expression, received '<'?

I'm facing an issue with my code. It works perfectly on my computer, but when I move it to the server, I encounter the following error. Error: Uncaught SyntaxError: expected expression, got '<' Here is the code snippet causing the prob ...

input value does not change when the "keyup" event is triggered

I'm encountering an issue with the code below. The code is for a simple To Do app using Javascript. I followed a tutorial step by step, but my app isn't functioning as expected. When I press the enter key, the input value should be added to the l ...

Establish validation parameters for uploading multiple files

I need to implement client-side validation for my FileUpload control to ensure that users can only select up to 10 images. While I already have the server-side code in place, I now want to add client-side validation as well. Sample Code: <asp:FileUplo ...

How to securely upload and generate a permanent link for the contents of a zip file using express js

I am new to Javascript and Node JS. I have a challenge of uploading a zip file containing only pictures and creating permanent links for these pictures. Currently, I can upload a zip file and extract its contents using the following code snippet: var expr ...

Trouble getting search filter to function properly on an array of objects in a Vue JavaScript application

Can someone help me with integrating this code into my project? Here is the code I am referencing: http://jsfiddle.net/dkmmhf5y/701/ This snippet shows my JavaScript file, please disregard the 'test' data var app = new Vue ( { el: &apos ...

Axios and Postman generate unique X-CSRF tokens

Why does the X-CSRF token I receive from my axios request differ from the one I get in Postman? Here is how I am retrieving it: headers: { "X-CSRF-Token": "FETCH" } Furthermore, I am unable to use the X-CSRF token from my axios request in Postman as it ...

Successful AJAX Post request functioning exclusively within the Web Console (Preview)

When a user clicks on an element on the website, I have a simple AJAX request to send the ID of that element. However, the script only works in the Web Console under the Network -> Preview section and this issue occurs across all browsers. Here is the ...

How to effectively filter a JSON array using multiple keys?

I need help filtering my JSON data by finding the objects with key 'status' equal to 'p' within the lease array. I attempted to use the following function, but it did not achieve the desired result: myActiveContractItems.filter((myActiv ...

Having trouble with the Jquery click event not functioning on an interactive image map in Chrome browser

I currently have an interactive image-map embedded on my website. Here is the HTML code: <div id="italy-map" class="affiancato verticalmenteAllineato"> <div id="region-map"> <img src="./Immagini/transparent.gif" title="Click on ...