Another package we’re going to need is passport
. Passport is an awesome tool to handle authentication. It can handle tons of authentication methods an in particular, we’re going to pair it with passport-local
, to handle authentication ourselves without relying on 3rd part sites.
Install them:
npm install passport passport-local
Import those libraries like this:
const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy
Now let’s instruct Passport to use the LocalStrategy
strategy to handle logins. What we add now will be used whenever we want to log in users to our system (something we’ll do very soon).
We pass an object of options, which we need because we don’t have a username
field, but we use email
instead, and we tell Passport to use that as the username (as it expects a username).
Next, we add a callback function, which will be called when Passport has detected the 2 fields are present in the request.
Then, we add some logic to check if the email and password are both there (might be redundant, but..), we check if we have a user in the database with that email, using User.findOne()
, a function provided by Sequelize.
If not, we call the done()
function passing an error message.
Same thing if the password is not valid (something we check with the isPasswordValid()
function we added in the last lesson).
Finally, if the user is found, and the password is valid, we call done() passing the user
object. Passport will know what to do next.
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
}, async function (email, password, done) {
if (!email || !password ) {
done('Email and password required', null)
return
}
const user = await User.findOne({ where: {email: email}})
if (!user) {
done('User not found', null)
return
}
const valid = await user.isPasswordValid(password)
if (!valid) {
done('Email and password do not match', null)
return
}
done(null, user)
}))
We also need to call 2 methods here: serializeUser
and deserializeUser
, passing in a function for each of them, to instruct Passport what is the data we want to send to the client, and how to retrieve our users from the database, given the user information:
passport.serializeUser((user, done) => {
done(null, user.email)
})
passport.deserializeUser((email, done) => {
User.findOne({ where: {email: email}}).then(user => {
done(null, user)
})
})
Now we need to add the Passport middleware to Express, adding those 2 function calls:
passport.initialize()
to initialize Passportpassport.session()
to handle login sessions
as middleware.
We add this after the call to express-sessions
:
server.use(
session({
secret: '343ji43j4n3jn4jk3n', //enter a random string here
resave: false,
saveUninitialized: true,
name: 'nextbnb',
cookie: {
secure: false, //CRITICAL on localhost
maxAge: 30 * 24 * 60 * 60 * 1000 //30 days
},
store: sessionStore
}),
passport.initialize(),
passport.session()
)