Skip to content

Instantly share code, notes, and snippets.

@cadd
Created October 30, 2019 12:01
Show Gist options
  • Save cadd/ea1fd8be22768f78158f72fec603d9f7 to your computer and use it in GitHub Desktop.
Save cadd/ea1fd8be22768f78158f72fec603d9f7 to your computer and use it in GitHub Desktop.
Express w/ Passport JWT/Cookie Auth
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const passportJWT = require('passport-jwt');
const JWTStrategy = passportJWT.Strategy;
const bcrypt = require('bcrypt');
const { secret } = require('./keys');
const UserModel = require('./models/user');
passport.use(new LocalStrategy({
usernameField: username,
passwordField: password,
}, async (username, password, done) => {
try {
const userDocument = await UserModel.findOne({username: username}).exec();
const passwordsMatch = await bcrypt.compare(password, userDocument.passwordHash);
if (passwordsMatch) {
return done(null, userDocument);
} else {
return done('Incorrect Username / Password');
}
} catch (error) {
done(error);
}
}));
passport.use(new JWTStrategy({
jwtFromRequest: req => req.cookies.jwt,
secretOrKey: secret,
},
(jwtPayload, done) => {
if (Date.now() > jwtPayload.expires) {
return done('jwt expired');
}
return done(null, jwtPayload);
}
));
const express = require('express');
const passport = require('passport');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const keys = require('../keys');
const UserModel = require('../models/user');
const router = express.Router();
router.post('/register', async (req, res) => {
const { username, password } = req.body;
// authentication will take approximately 13 seconds
// https://pthree.org/wp-content/uploads/2016/06/bcrypt.png
const hashCost = 10;
try {
const passwordHash = await bcrypt.hash(password, hashCost);
const userDocument = new UserModel({ username, passwordHash });
await userDocument.save();
res.status(200).send({ username });
} catch (error) {
res.status(400).send({
error: 'req body should take the form { username, password }',
});
}
});
router.post('/login', (req, res) => {
passport.authenticate(
'local',
{ session: false },
(error, user) => {
if (error || !user) {
res.status(400).json({ error });
}
/** This is what ends up in our JWT */
const payload = {
username: user.username,
expires: Date.now() + parseInt(process.env.JWT_EXPIRATION_MS),
};
/** assigns payload to req.user */
req.login(payload, {session: false}, (error) => {
if (error) {
res.status(400).send({ error });
}
/** generate a signed json web token and return it in the response */
const token = jwt.sign(JSON.stringify(payload), keys.secret);
/** assign our jwt to the cookie */
res.cookie('jwt', jwt, { httpOnly: true, secure: true });
res.status(200).send({ username });
});
},
)(req, res);
});
module.exports = router;
const mongoose = require('mongoose');
const { Schema } = mongoose;
const userSchema = new Schema({
username: {
type: String,
index: true,
unique: true,
dropDups: true,
required: true,
},
passwordHash: { //salted and hashed using bcrypt
type: String,
required: true,
},
});
const User = mongoose.model('User', userSchema);
module.exports = User;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment