Passport.js consistently returns an unauthorized status for every request, even when a valid token is provided, or it author

I am facing issues with my Passport.js functions not authenticating users properly.

When I use the current form, it always returns "unauthorized" for all requests:

import passport from 'passport'
import passportJWT from 'passport-jwt'
import userModel from '../user/user.model'
import {Request, Response, NextFunction} from 'express'

export default class PassportController{

    static async setup(app: express.Application){
        const JWTStrategy = passportJWT.Strategy
        const ExtractJwt = passportJWT.ExtractJwt
        const config = {
            jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
            secretOrKey: process.env.JWT_SECRET,
            issuer: 'DepoApp',
            
        }

        passport.use(userModel.createStrategy())
        passport.use(new JWTStrategy(
            config, 
            (payload, done) => {
                userModel.findOne({_id: payload.id}, (err:any, user:any) => {
                    if(err) {
                        return done(err, false)
                    }
                    else if(user){
                        return done(null, user)
                    }
                    else{
                        return done(null, false)
                    }
                })
            }
        ))
    }

    static async auth(req: Request, res: Response, next: NextFunction){
        await passport.authenticate('jwt', {session: false})(req, res, next)
    }
}

Changing the auth method as shown below causes it to authorize all users regardless of their token:

static async auth(req: Request, res: Response, next: NextFunction){
        await passport.authenticate('jwt', {session: false})
        next()
    }

I suspect that the issue lies in the improper implementation of the middleware auth. Please guide me on how to configure it correctly.

In my index.ts file, I simply call PassportController.setup()

Note #1: Sessions are not being used

Note #2: The user model does not have a username field and uses _id as the default key. User model structure is as follows:

import mongoose from 'mongoose'
import { Schema } from 'mongoose'
import Permits from './permits.enum'
import passportLocalMongoose from 'passport-local-mongoose'

const userSchema = new Schema({
    _id: {type: String},
    first_name: {type: String, required: true},
    last_name: {type: String, required: true},
    phone: {type: String, required: true},
    mail: {type: String, required: true, lowercase: true, trim: true, unique: true},
    permits: [{type: String, enum: Permits, default: []}],
},
{
    collection: 'users',
    timestamps: true,
})

userSchema.plugin(passportLocalMongoose, {usernameField: '_id'})
const userModel = mongoose.model('User', userSchema)

export default userModel

I have experimented with different approaches to modify the auth method as mentioned above. Additionally, when I inspect the contents of payload within JWTStrategy(), nothing is logged (it appears empty as if the function was never called).

A similar question suggested issues with routes, but in my case, everything seems to be in order.

Routes:

this.app.route('/api/depo')
        .get(PassportController.auth, DepoController.getAll)
        .post(PassportController.auth, DepoController.post)
        
this.app.route('/api/depo/:id')
        .get(PassportController.auth, DepoController.getById)
        .patch(PassportController.auth, DepoController.patchById)
        .delete(PassportController.auth, DepoController.deleteById)


this.app.route('/api/no-gdpr/depo/')
        .get(DepoController.getAllNoGDPR)

this.app.route('/api/no-gdpr/depo/:id')
        .get(DepoController.getOneNoGDPR)

Answer №1

Hurrah! The issue has finally been resolved!

After a thorough investigation, it was discovered that there were two primary errors leading to this situation.

  1. The JWT token lacked the issuer property, causing the entire strategy to be skipped as passport.js had already rejected the request. To rectify this, the issuer field was removed from the config:
const config = {
     jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
     secretOrKey: process.env.JWT_SECRET,
}

Subsequently, another error surfaced - version 5.* of mongoose removed callbacks from the findOne() method. Consequently, the Strategy callback needed to be refactored:

const JWTstrategy = new passportJWT.Strategy(
    config, 
    (payload, done) => {
        var user
        try{
            user = userModel.findOne({_id: payload.user._id})
        }catch(err){
            return done(err, false)
        }
        if(user){
            return done(null, user)
        }
        else{
            return done(null, false)
        }
    }
)

The updated setup function now appears as follows:


    static async setup() {

      const ExtractJwt = passportJWT.ExtractJwt

      const config = {
        jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
        secretOrKey: process.env.JWT_SECRET,
      }

      const JWTstrategy = new passportJWT.Strategy(
        config,
        (payload, done) => {
          var user
          try {
            user = userModel.findOne({
              _id: payload.user._id
            })
          } catch (err) {
            return done(err, false)
          }
          if (user) {
            return done(null, user)
          } else {
            return done(null, false)
          }
        }
      )


      passport.use(userModel.createStrategy())
      passport.use('jwt', JWTstrategy)

      console.log('[PASSPORT]: setup finished.')
    }

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

Trouble encountered with uploading files using Multer

I am facing an issue with uploading images on a website that is built using React. The problem seems to be related to the backend Node.js code. Code: const multer = require("multer"); // Check if the directory exists, if not, create it const di ...

Customize the color of the Material-UI Rating Component according to its value

Objective I want to dynamically change the color of individual star icons in a Ratings component (from material-ui) based on the value selected or hovered over. For example, hovering over the 1st star would turn it red, and hovering over the 5th star woul ...

Is your Typescript struggling to infer types correctly?

I created a function that converts an Array into a Map: function toMap<T,TKey,TElement>(items: Array<T>, keySelector: (item: T) => TKey, elementSelector: (item: T) => TElement ): Map<TKey,TElement> { var ma ...

Make sure to properly check the size of the image before uploading it in express js

Below is the code I have written to verify if an image's size and width meet the specified criteria: im.identify(req.files.image,function (err,features) { //console.log(features); if(features.width<1000 ...

Describing a function in Typescript that takes an array of functions as input, and outputs an array containing the return types of each function

Can the code snippet below be accurately typed? function determineElementTypes(...array: Array<(() => string) | (() => number) | (() => {prop: string}) | (() => number[])>) { /// .. do something /// .. and then return an array ...

Any tips on how to export the index file from Firebase after switching from using require statements to import statements?

As I transition from using requires to importing only in my code, I encountered a challenge when adding "type": "module". After resolving several issues, one problem remains. Initially, I had exports.expressApi = functions.https.onReque ...

Develop a Nativescript Angular component dynamically

Is there a way for me to dynamically generate a Component and retrieve a View object to insert into a StackLayout? ...

Transferring Server Port from Mac OS to Ubuntu results in failure (Express + ReactJS)

After porting the exact copy and settings to Ubuntu, I encountered an issue where I receive a 'Failed to load resource: net::ERR_EMPTY_RESPONSE' error via Chrome DevTools. The Express server is running with PM2, and MongoDB is also running as a ...

What is the best way to renew a Firebase IdToken once it has expired?

I have set up my backend with express and am using the Firebase Admin SDK to send a token back to the client. Currently, the token expires after 1 hour. I noticed on Firebase that it's not possible to change the expiration property as users are suppos ...

Clear the input field once an item has been successfully added to the array

I'm working on a CRUD application using an array. Once I add an item to the array, the HTML input field doesn't clear or reset. I've searched online but couldn't find a reset method in Angular. How can I clear the input field after addi ...

The Unhandled Promise Rejection Warning in mocha and ts-node is due to a TypeError that arises when attempting to convert undefined or null values

I've been encountering issues while setting up ts-node with mocha, as the test script consistently fails. I attempted to run the following commands: mocha --require ts-node/register --extensions ts,tsx --watch --watch-files src 'src/**/*.spec.{ ...

In ES6, how can we achieve the same functionality as exports.someFunction?

I'm struggling to understand how to execute the code provided below. What would be the ES6 equivalent of this code snippet? \\controller.js exports.someFunction = [middleware1, middleware2, (req, res) => {...}] \\app.js const c ...

The JSX element with type 'Component' does not support any construct or call signatures at this time

I am facing an issue with the following code snippet const pageArea = (Component:ReactNode,title:string) => ({ ...props }) => { return ( <> <div> { Component && (<Component { ...

Express encountered a simple web application error

Greetings, this marks my debut post. As a coding novice, I have been following tutorials on opentutorials.org/course/2136/11950 I attempted to troubleshoot errors in my code, but unfortunately I've hit a roadblock. Upon accessing the site, it displa ...

The nested jade elements are failing to render

If I have a jade setup with 3 files as follows: 1. //layout.jade doctype html html body block content 2. //index.jade extends layout block content h1 Animals block cat block dog 3. //animals.jade extends index block cat p Meow block ...

Issue with TypeScript retrieving value from an array

Within my component.ts class, I have defined an interface called Country: export interface Country{ id: String; name: String; checked: false; } const country: Country[] = [ { id: 'India', name: 'India', checked: false}, { ...

Can you provide guidance on configuring Express Gateway to establish secure connections with my services?

Currently, I have set up express-gateway to connect with a backend service on my machine through a unique port. The setup is functioning properly as the gateway acts as a proxy, conducting security checks and jwt authentication. This ensures that only au ...

What factors contribute to 'tslib' having more downloads than 'typecrypt'?

How is it possible that 'tslib', a library for 'typescript', has more downloads than 'typescript' itself? If one does not use 'typescript', then they cannot utilize 'tslib' as well. Just because someone us ...

Decryption of Passwords Encrypted with SHA256 in NodeJS

I'm currently diving into the world of encryption and decryption for passwords using NodeJS. I've got my password hashed using SHA256 in my code. Now, the question is: how do I go about decrypting that data? exports.getHashedPassword = function(p ...

Angular // binding innerHTML data

I'm having trouble setting up a dynamic table where one of the cells needs to contain a progress bar. I attempted using innerHTML for this, but it's not working as expected. Any suggestions on how to approach this? Here is a snippet from my dash ...