A simple implementation of a LocalStrategy for passport.
npm i
npm start -s
npm test -s
or
npm run test:watch
## Restify Example
```bash
npm install
node restify.js
install 'curl'
run restify-test.sh
-or-
curl -H "Content-Type: application/json" -X POST -d '{"username":"scott","password":"password"}' http://localhost:3000/login
Preliminary Stuff. Require your packages etc.
var express = require('express');
//var restify = require('restify'); //(for restify)
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy; // a 'strategy' to use for passport
var bodyParser = require('body-parser'); // be able to parse form elements
var app = express();
//var app = restify.createServer();
You can change this to pull from MySQL, Mongo, Etc.
var users = [
{id: 1, username: 'bob', password: 'secret', email: 'bob@example.com'}
, {id: 2, username: 'scott', password: 'password', email: 'scott@example.com'}
];
Some examples you see this calling Mongo User.find, or something similar, essentially this is just a way to invoke a callback, and search for users. You can also use this to compare passwords if you want, but I'm not doing that here.
function findByUsername(username, callback) {
for (var i = 0, len = users.length; i < len; i++) {
var user = users[i];
if (user.username === username) {
// callback takes arguments (error,user)
return callback(null, user);
}
}
return callback(null, null);
}
This tells passport to "use" a LocalStrategy and to map the username,password fields.
passport.use(new LocalStrategy({
// this maps the file names in the html file to the passport stuff
usernameField: 'username',
passwordField: 'password'
},
This calls our db search function and invokes the callback 'done' with the arguments it's expecting. I'm also performing my password comparison here.
findByUsername(username, function (err, user) {
if (err) {
return done(err);
}
if (!user) {
console.log('bad username');
return done(null, false, {message: 'Incorrect username.'});
} else {
if (user.password === password) {
console.log('good username and password');
return done(null, user);
} else {
console.log('good username and bad password');
return done(null, false, {message: 'Incorrect password.'});
}
}
});
This tells the app to use the public folder and to parse the body for form elements.
// configure app
app.use('/', express.static('public')); // set to display index.html could also use sendFile
//app.use(bodyParser.json()); // use for JSON w/restify
app.use(bodyParser.urlencoded({extended: false})); // use for forms
This is the custom callback for LocalStrategy that takes the arguments: error, user, and info.
// custom callback
app.post('/login', function (req, res, next) {
passport.authenticate('local', function (err, user, info) {
console.log(err, user, info);
if (user) {
res.send({user: user});
} else {
res.send({error: err, info: info});
}
})(req, res, next);
});
Finally, tell the app to listen to a port.
app.listen(3000);
Updates 22-11-2018 by rkristelijn
-
npm i --save express
-> added inpackage.json
- split app and server to be able to set up tests
- added mocha tests before optimizing code
- test route with login
- optimize code
- remove console, of move behind
if (debug)
- var -> const / let
- remove console, of move behind
- npm outdated: passport from 0.3.2 to 0.4.0
ToDo
-
logout
-
create SPA to make calls
-
create secure route
-
single file version
-
multi file version
For what I can read on passport at npmjs.com the current state of the project doesn't cope with follow-up requests, because there is no session and the session isn't persistant throughout the calls. For that we need
serialize
middleware. On top of that we may need cookie support and/or session support. Only if this is created we can use the logout feature. This will be created on a branch