Shifatul
Shifatul

Reputation: 2318

Use Passport Local & JWT Strategy on same app (on same route)

so my route (for '/dash') looks like this:

// validating using JWT
router.post('/dash', passport.authenticate('jwt', {session: false}), function (req, res) {
    res.json({'success': true});
});

// validating using LOCAL
router.post('/dash', authenticationHelpers.isAuth, function (req, res) {
    res.json({'success': true});
});

// authenticationHelpers.isAuth
function isAuth(req, res, next) {
    if (req.isAuthenticated())
        return next();
    res.status(401).json({"authenticated": false});
}

So, how do I use both Local & JWT Strategy on same app (on same route) ? How do I combine them both.

Note: Local for web app, JWT for mobile app

Upvotes: 2

Views: 968

Answers (2)

Fırat Taşkın
Fırat Taşkın

Reputation: 117

I need same thing for my app, I dont want to separate frontend and backend and i want to use my codes with postman without session too. So i solve problem like this,

Firstly i changed my "jwtFromRequest", so i can look for jwt from header and sesssion together

const opts = {};
opts.jwtFromRequest = ExtractJwt.fromExtractors([
    ExtractJwt.fromAuthHeaderAsBearerToken(),
    (req) => req.session?.jwt || ''
]);

opts.secretOrKey = process.env.APP_SECRET;

module.exports = function (passport) {
    passport.use(
        new JwtStrategy(opts, (jwtPayload, done) => {

i defined my login root (i have 2 root)

router.post(
    'auth/login',
    passport.authenticate('local', {
        failureRedirect: '/auth/login',
        failureFlash: true
    }),
    asyncHandler(AuthenticationController.login)
);

router.post(
    'api/login',
    [body('email').isEmail(), body('password').isLength({ min: 1 })],
    asyncHandler(AuthenticationController.loginJwt)
);

my login functions at Controller:

login: async (req, res, next) => {
    const jwtToken = req.user.generateJwt();
    req.session.jwt = jwtToken;
    res.redirect('/');
},
loginJwt: async (req, res) => {
    const lowerMail = (req.body.email || '').toLowerCase();
    const user = await User.findOne({ email: lowerMail })

    if (!user || !(await user.isValidPassword(req.body.password))) {
        return res.status(401).json(errRes(__l('auth.emailAndPasswordDoNotMatch')));
    }

    const token = user.generateJwt();

    return res.json(
        stdRes(__l('auth.successfullyLoggedIn'), {
            user: {
                _id: user._id,
                name: user.name,
                email: user.email
            },
            access_token: token
        })
    );
},

and lastly my middleware for check authentication

function checkAuth(req, res, next) {
    passport.authenticate('jwt', (err, user) => {
        if (err) return next(err);
        if (!user) {
            if (req.xhr || req.headers.accept.indexOf('json') > -1) {
                return res.status(401).json(errRes(__l('auth.userIsNotAuthenticated')));
            }
            return res.redirect('/auth/login');
        }
        req.user = user;
        return next();
    })(req, res, next);
}
router.get('/', [checkAuth], DashboardController.homePage);

Upvotes: 0

Shifatul
Shifatul

Reputation: 2318

Finally figured it out.

Modified isAuth function:

function isAuth(req, res, next) {
    if (req.headers.authorization) {
        passport.authenticate('jwt', {session: false}, function (err, user, info) {
            if ((!err || !info) && user) {
                req.user = user;
                return next();
            }
            res.status(401).json({authenticated: false, message: "Login expired."});
        })(req, res, next);
    } else {
        if (req.isAuthenticated())
            return next();
        res.status(401).json({authenticated: false});
    }
}

Suggestions are welcomed...

Upvotes: 4

Related Questions