-
-
Save LeeWarnock/873aa18b59a94af7cd436b0eeb8c7443 to your computer and use it in GitHub Desktop.
How To Integrate Sails and Passport
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| . |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // config/application.js | |
| var passport = require('passport') | |
| , LocalStrategy = require('passport-local').Strategy; | |
| // some static users | |
| var users = [ | |
| { id: 1, username: 'bob', password: 'secret', email: '[email protected]' } | |
| , { id: 2, username: 'joe', password: 'birthday', email: '[email protected]' } | |
| ]; | |
| // 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); | |
| }) | |
| }); | |
| } | |
| )); | |
| // export | |
| module.exports = { | |
| // Name of the application (used as default <title>) | |
| appName: "Sails Application", | |
| // Port this Sails application will live on | |
| port: 1337, | |
| // The environment the app is deployed in | |
| // (`development` or `production`) | |
| // | |
| // In `production` mode, all css and js are bundled up and minified | |
| // And your views and templates are cached in-memory. Gzip is also used. | |
| // The downside? Harder to debug, and the server takes longer to start. | |
| environment: 'development', | |
| // Custom express middleware - we use this to register the passport middleware | |
| express: { | |
| customMiddleware: function(app) | |
| { | |
| app.use(passport.initialize()); | |
| app.use(passport.session()); | |
| } | |
| } | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // api/controllers/AuthController.js | |
| 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; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // api/policies/authenticated.js | |
| // We use passport to determine if we're authenticated | |
| module.exports = function(req, res, next) | |
| { | |
| if (req.isAuthenticated()) | |
| return next(); | |
| res.redirect('/login') | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // views/auth/login.ejs | |
| <form action="/login" method="post"> | |
| <div> | |
| <label>Username:</label> | |
| <input type="text" name="username"/><br/> | |
| </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> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // config/policies.js | |
| /** | |
| * Policy defines middleware that is run before each controller/controller. | |
| * Any policy dropped into the /middleware directory is made globally available through sails.middleware | |
| * Below, use the string name of the middleware | |
| */ | |
| module.exports.policies = { | |
| // default require authentication | |
| // see api/policies/authenticated.js | |
| '*': 'authenticated', | |
| // whitelist the auth controller | |
| 'auth': | |
| { | |
| '*': true | |
| } | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Routes | |
| // ********************* | |
| // | |
| // This table routes urls to controllers/actions. | |
| // | |
| // If the URL is not specified here, the default route for a URL is: /:controller/:action/:id | |
| // where :controller, :action, and the :id request parameter are derived from the url | |
| // | |
| // If :action is not specified, Sails will redirect to the appropriate action | |
| // based on the HTTP verb: (using REST/Backbone conventions) | |
| // | |
| // GET: /:controller/read/:id | |
| // POST: /:controller/create | |
| // PUT: /:controller/update/:id | |
| // DELETE: /:controller/destroy/:id | |
| // | |
| // If the requested controller/action doesn't exist: | |
| // - if a view exists ( /views/:controller/:action.ejs ), Sails will render that view | |
| // - if no view exists, but a model exists, Sails will automatically generate a | |
| // JSON API for the model which matches :controller. | |
| // - if no view OR model exists, Sails will respond with a 404. | |
| // | |
| module.exports.routes = { | |
| // To route the home page to the "index" action of the "home" controller: | |
| '/': { | |
| controller: 'home' | |
| }, | |
| // Custom routes for login: | |
| 'get /login': { | |
| controller: 'auth', | |
| action: 'login' | |
| }, | |
| 'post /login': { | |
| controller: 'auth', | |
| action: 'process' | |
| } | |
| // If you want to set up a route only for a particular HTTP method/verb | |
| // (GET, POST, PUT, DELETE) you can specify the verb before the path: | |
| // 'post /signup': { | |
| // controller : 'user', | |
| // action : 'signup' | |
| // } | |
| // Keep in mind default routes exist for each of your controllers | |
| // So if you have a UserController with an action called "juggle" | |
| // a route will be automatically exist mapping it to /user/juggle. | |
| // | |
| // Additionally, unless you override them, new controllers will have | |
| // create(), find(), findAll(), update(), and destroy() actions, | |
| // and routes will exist for them as follows: | |
| /* | |
| // Standard RESTful routing | |
| // (if index is not defined, findAll will be used) | |
| 'get /user': { | |
| controller : 'user', | |
| action : 'index' | |
| }, | |
| 'get /user/:id': { | |
| controller : 'user', | |
| action : 'find' | |
| }, | |
| 'post /user': { | |
| controller : 'user', | |
| action : 'create' | |
| }, | |
| 'put /user/:id': { | |
| controller : 'user', | |
| action : 'update' | |
| }, | |
| 'delete /user/:id': { | |
| controller : 'user', | |
| action : 'destroy' | |
| } | |
| */ | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment