Passport.js + Meteor accounts
// http://blog.thebakery.io/meteor-accounts-auth-with-passportjs/ | |
import bcrypt from 'bcrypt'; | |
import crypto from 'crypto'; | |
import express from 'express'; | |
import mongoose from 'mongoose'; | |
import passport from 'passport'; | |
import { Strategy as LocalStrategy } from 'passport-local'; | |
import { BasicStrategy } from 'passport-http'; | |
const User = mongoose.model('users', new mongoose.Schema({ | |
_id: String, | |
}, { | |
collection: 'users', | |
})); | |
function comparePasswords(password, hash, callback) { | |
bcrypt.compare(crypto.createHash('sha256').update(password).digest('hex'), hash, callback); | |
} | |
function deserializeUserPassport(id, done) { | |
User.findOne({ _id: id }, (err, userModel) => { | |
if (err) { | |
done(err); | |
} else { | |
if (!userModel) { | |
done(); | |
return; | |
} | |
done(null, userModel.toJSON()); | |
} | |
}); | |
} | |
function getUserPassport(username, password, done) { | |
User.findOne({ | |
'emails.address': username, | |
}, (findError, userModel) => { | |
if (findError) { | |
return done(findError); | |
} | |
if (!userModel) { | |
return done(null, false, { message: 'Incorrect username.' }); | |
} | |
const user = userModel.toJSON(); | |
comparePasswords(password, user.services.password.bcrypt, (hashError, goodPassword) => { | |
if (hashError) { | |
return done(hashError); | |
} | |
if (!goodPassword) { | |
return done(null, false, { message: 'Incorrect password.' }); | |
} | |
return done(null, user); | |
}); | |
}); | |
} | |
passport.serializeUser((user, done) => done(null, user._id)); | |
passport.deserializeUser(deserializeUserPassport); | |
// Passport auth strategy for basic username + password setup | |
// if you only want to use this server as an API endpoint, you can just remove this | |
// and keep BasicStrategy below | |
passport.use(new LocalStrategy(getUserPassport)); | |
// Passport auth strategy for Basic Auth | |
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization | |
passport.use(new BasicStrategy(getUserPassport)); | |
const app = express(); | |
app.use(require('cookie-parser')()); | |
app.use(require('body-parser').urlencoded({ extended: true })); | |
app.use(require('express-session')({ secret: 'keyboard cat', resave: true, saveUninitialized: true })); | |
app.use(passport.initialize()); | |
app.use(passport.session()); | |
const port = process.env.PORT || 3007; | |
app.get('/', (req, res) => { | |
// When logged in user object is attached to the request | |
if (!req.user) { | |
res.redirect('/login'); | |
return; | |
} | |
res.send(`Hello ${req.user.emails[0].address}`); | |
}); | |
app.get('/login', (req, res) => { | |
res.send(`<form action="/login" method="post"> | |
<div> | |
<label>Username:</label> | |
<input type="text" name="username"/> | |
</div> | |
<div> | |
<label>Password:</label> | |
<input type="password" name="password"/> | |
</div> | |
<div> | |
<input type="submit" value="Log In"/> | |
</div> | |
</form>`); | |
}); | |
app.post('/login', passport.authenticate('local', { | |
successRedirect: '/', | |
failureRedirect: '/error', | |
})); | |
// /api endpoint gets authentication via Basic Auth | |
// you auth by sending a base64 encoded username:password string via Authorization header | |
// see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization | |
app.use('/api', passport.authenticate('basic', { session: false })); | |
app.post('/api/ping', (req, res) => { | |
res.send(`pong ${req.user.emails[0].address}`); | |
}); | |
// eslint-disable-next-line | |
app.listen(port, async () => { | |
// eslint-disable-next-line | |
console.log(`API server running on ${port}!`); | |
await mongoose.connect(process.env.DATABASE_URL, { useNewUrlParser: true, useUnifiedTopology: true }); | |
// eslint-disable-next-line | |
console.log('Connected to the database'); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment