Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
How To Integrate Sails and Passport

#Prerequisites#

#Steps#

  1. Create a new Sails application via sails new <appName>.
  2. Change your working directory to the root directory of the new Sails application via cd <appName>.
  3. Merge application.js with config/application.js.
  4. Merge policies.js with config/policies.js.
  5. Merge routes.js with config/routes.js.
  6. Merge authenticated.js with api/policies/authenticated.js.
  7. Create api/controllers/AuthController.js.
  8. If you are using a traditional, server-generated UI, then create views/auth/login.ejs
var passport = require('passport'),
LocalStrategy = require('passport-local').Strategy;
// some static users
var users = [{
id: 1,
username: 'bob',
password: 'secret',
email: 'bob@example.com'
}, {
id: 2,
username: 'joe',
password: 'birthday',
email: 'joe@example.com'
}];
// helper functions
function findById(id, fn) {
var idx = id - 1;
if (users[idx]) {
fn(null, users[idx]);
} else {
fn(new Error('User ' + id + ' does not exist'));
}
}
function findByUsername(username, fn) {
for (var i = 0, len = users.length; i < len; i++) {
var user = users[i];
if (user.username === username) {
return fn(null, user);
}
}
return fn(null, null);
}
// Passport session setup.
// To support persistent login sessions, Passport needs to be able to
// serialize users into and deserialize users out of the session. Typically,
// this will be as simple as storing the user ID when serializing, and finding
// the user by ID when deserializing.
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
findById(id, function(err, user) {
done(err, user);
});
});
// Use the LocalStrategy within Passport.
// Strategies in passport require a `verify` function, which accept
// credentials (in this case, a username and password), and invoke a callback
// with a user object. In the real world, this would query a database;
// however, in this example we are using a baked-in set of users.
passport.use(new LocalStrategy(
function(username, password, done) {
// asynchronous verification, for effect...
process.nextTick(function() {
// Find the user by username. If there is no user with the given
// username, or the password is not correct, set the user to `false` to
// indicate failure and set a flash message. Otherwise, return the
// authenticated `user`.
findByUsername(username, function(err, user) {
if (err) {
return done(err);
}
if (!user) {
return done(null, false, {
message: 'Unknown user ' + username
});
}
if (user.password != password) {
return done(null, false, {
message: 'Invalid password'
});
}
return done(null, user);
});
});
}));
module.exports = {
// SNIP ...
// Custom express middleware - we use this to register the passport middleware
express: {
customMiddleware: function(app) {
app.use(passport.initialize());
app.use(passport.session());
}
}
};
/*jshint node:true */
/*---------------------
:: Auth
-> controller
---------------------*/
var passport = require('passport');
var AuthController = {
login: function(req, res) {
res.view();
},
process: function(req, res) {
passport.authenticate('local', function(err, user, info) {
if ((err) || (!user)) {
res.redirect('/login');
return;
}
req.logIn(user, function(err) {
if (err) {
res.view();
return;
}
res.redirect('/');
return;
});
})(req, res);
},
logout: function(req, res) {
req.logout();
res.redirect('/');
}
};
module.exports = AuthController;
// We use passport to determine if we're authenticated
module.exports = function(req, res, next) {
'use strict';
// Sockets
if(req.isSocket)
{
if(req.session &&
req.session.passport &&
req.session.passport.user)
{
return next();
}
res.json(401);
}
// HTTP
else
{
if(req.isAuthenticated())
{
return next();
}
// If you are using a traditional, server-generated UI then uncomment out this code:
/*
res.redirect('/login');
*/
// If you are using a single-page client-side architecture and will login via socket or Ajax, then uncomment out this code:
/*
res.status(401);
res.end();
*/
}
};
<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="Submit"/>
</div>
</form>
<p><small>Hint - bob:secret</small></p>
module.exports.policies = {
// default require authentication
// see api/policies/authenticated.js
'*': 'authenticated',
// whitelist the home controller, so the client-side app can be sent down
// If you are using a single-page client-side architecture, then uncomment out this code:
/*
'home': {
'*': true
},
*/
// whitelist the auth controller
'auth': {
'*': true
}
};
module.exports.routes = {
// SNIP ...
// Custom routes for login:
'get /login': {
controller: 'auth',
action: 'login'
},
'post /login': {
controller: 'auth',
action: 'process'
}
// SNIP ...
};
@paulmand3l

This comment has been minimized.

Copy link

@paulmand3l paulmand3l commented Feb 18, 2014

Is the req.logIn function at AuthController.js@22 documented anywhere? I can't find it for the life of me.

@NizarBlond

This comment has been minimized.

Copy link

@NizarBlond NizarBlond commented Mar 22, 2014

It is part of Passport JS documentation, see passportjs.org/Login

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment