Search code examples
javascriptnode.jsexpressexpress-jwtpassport-jwt

How to get express route to go through passport for authentification


I'm recently changing a boilerplate I made in es6 to a slightly older version es5. I had to recreate the export, require instead of using imports and the routing is functional now.

I have a structure like this:

index.js (app)
api/index.js (/api endpoint)
api/auth.js (/api/auth endpoint)
api/protected.js (/api/protected endpoint)

In my auth route I have the login and register functionning and generating a token:

const token = jwt.sign({id: req.body.username},  config.jwtSecret)

In my protected.js I have the following:

const express = require('express');
const router = express.Router();
const passport = require('../config/passport');
router.use(passport.initialize({ session: false }));
router.use(passport.session());
router.get('/test', passport.authenticate('jwt') , (req, res) => {
    res.status(200).json({ message: 'Hello sweetie', auth: req.isAuthenticated(), user: req.session.passport.user})
});
module.exports = router;

And in my passport.js

const
  passport = require('passport'),
  config = require('./../config'),
  passportJwt = require('passport-jwt'),
  JwtStrategy = passportJwt.Strategy,
  ExtractJwt = passportJwt.ExtractJwt,
  userSchema = require('./../schemas/userSchema');

passport.serializeUser(function(user, done) {
    console.log(JSON.stringify(user));
    done(null, user[0].username);
});

passport.deserializeUser(function(username, done) {
    console.log('DESER -- '+username);
    userSchema.checkUsername(username)
    .then(user => {
        console.log(user[0]);
        done(null, user[0]);
    })
    .catch(err =>{
        console.log(JSON.stringify(err));
    });
});

const jwtOptions = {
    secretOrKey: config.jwtSecret,
    jwtFromRequest: ExtractJwt.fromHeader('authorization'),
}

passport.use('jwt', new JwtStrategy(jwtOptions, function(jwt_payload, done) {
    console.log('Strategy: '+ jwt_payload.id);
    userSchema.checkUsername(jwt_payload.id)
    .then(user => {
        console.log(user[0].username);
        if(user[0]) return done(null, user)
        else return done(null, false)
    })
    .catch(err =>{
        console.log(JSON.stringify(err));
    });
}));

module.exports = passport;

The problem is when I try to access: 127.0.0.1:8080/api/protected/test with the token I got on login it give me a: Unauthorized

Furthermore the console.log inside the:

  • serializeUser
  • deserializeUser
  • jwt Strategy

Are never shown and thus I think the passport middleware isn't used.

How could I get the /protected routes to use the passport middleware?

Edit: I have tried printing the passport object and I can see my jwt strategy is indeed defined. So I don't see why it doesn't want to go through it.

There si a strategy


Solution

  • The problem is that your passport is looking for authorization header not Authorization header.

    Change your

    jwtFromRequest: ExtractJwt.fromHeader('authorization')

    to

    ExtractJwt.fromAuthHeaderAsBearerToken()

    so your options will look like

    const jwtOptions = {
        secretOrKey: config.jwtSecret,
        jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
    }
    

    Now what this does is passport will look for Authorization header with value bearer your_jwt_token. https://www.npmjs.com/package/passport-jwt