[How To] Implement Passport.js Authentication with Sails.js

Home / How To
[How To] Implement Passport.js Authentication with Sails.js
21August

[How To] Implement Passport.js Authentication with Sails.js

About the Author

Comments

    Chris Larson - August 24, 2013

    Thanks for sharing this. I have been looking for a good tutorial on using passport with sails.

    Reply
    Peter - August 27, 2013

    My form never ever redirects? i dont need to setup a policy?

    Reply
      Manas Sahoo - September 3, 2013

      Thanks for your valuable comment . I have included the policy authenticated.js

      Reply
    JRMLSTF - September 22, 2013

    I had to change the login form action to /process and add the following route to config/routes.js to make it works.

    Thanks for sharing !

    Reply
      Kamal Reddy - February 5, 2014

      What following route? I dont see anything.

      Reply
    Tyler - October 27, 2013

    Thanks for the write up.

    "http://localhost:1337/user/create?username=user&password=pass"

    In order for the API to work like this, there needs to be a controller as well. Because the tutorial creates just a user Model, this link will actually 404. I had to create an empty User controller for it to work, but it might make more sense to just rename the AuthController.

    Reply
    Paul - December 3, 2013

    Thanks for sharing, good stuff.

    typo in step 7

    you have to change ok to next or next to ok

    Reply
    Purplebadger - December 6, 2013

    Thanks for this example, but I'm struggling with the following error:

    Error: passport.initialize() middleware not in use

    It appears Passport isn't being initialised. I never see this message in the console when I start the app:

    console.log('Express midleware for passport');

    Any suggestions very welcome. This is driving me mad. :-(

    Reply
      Purplebadger - December 6, 2013

      It does seem to be authenticating users, btw. I'm getting that error when I call req.logIn in the controller.

      Reply
    Smit - April 16, 2014

    What about local registration process ?

    Reply
    Craig Roy - June 5, 2014

    .done in the passport.js service(line 18) will no longer work. It should be replaced with .exec instead.

    Reply
      Artem Pylypchuk - December 22, 2014

      The same applies to line #6, without this change session won't work (silently).

      Reply
    Edygar de Lima - November 5, 2014

    Quick tip: https://github.com/kasperisager/sails-generate-auth

    Reply
    jiarong - November 6, 2014

    This is a good example. (: helped me out real quick.

    Reply
    Artem Pylypchuk - December 22, 2014

    Maybe this was a good example some time ago, but now it isn't. It is extremely error-prone.
    I used the working one from https://github.com/kasperisager/sails-generate-auth (thanks @Edygar), but made it simpler (I don't need Facebook adapters or login with both username and e-mail).

    Literally almost any piece of code I reused from this example had errors in it.

    If you want to figure it out on your own, with invaluable educational experience, don't read my comment any further, and try making it to work! ;)

    First of all, in findById & findByUsername, you can't do User.findOne(query).done() anymore, you have to do User.findOne(id, function (err, user) { ... }); . In the case of findByUsername it trows an error, but findById fails silently (and you spend hours figuring out why session is not established after successful login).

    Next,
    bcrypt.genSalt(10, function(err, salt) {
    bcrypt.hash(user.password, salt, function(err, hash) {...} });
    doesn't work anymore (undocumented change in api?), one has to do
    bcrypt.hash(user.password, 10, function (err, hash) {...});

    Then, to set up the local strategy one has to declare something like this in services/passport.js and add it to config/bootstrap.js (a "passport.loadStrategies();" line):

    passport.loadStrategies = function () {
    this.use(new LocalStrategy({ passReqToCallback: true, usernameField: 'email' },
    function (req, username, password, done) {

    Note: passReqToCallback is useful when you want to localize messages returned, e.g. with i18n
    return done(null, false, {message: sails.__.apply(req, ['Error.Passport.Password.Wrong'])});
    otherwise, there will be no req object inside.

    Custom middleware is best inserted through an "authenticated" policy, which has to set up session variables (req.isAuthenticated() doesn't work), see how it's done e.g. like in https://github.com/kasperisager/sails-generate-auth, but the example there with "sessionAuth" policy is incomplete and "req.session.authenticated" variable doesn't get set, so one has to add some extra code into api/policies/passport.js.
    Inserting middleware Express-style through config/passport.js is obsolete (one has to use "http" variable, not "express") and seems to break interoperability of other middleware inside Sails.
    It is possible to set custom middleware config through config/http.js, but I don't think it is good to do it this way.

    And so on, because I think I might have omitted something.
    If you don't want any headache just use https://github.com/kasperisager/sails-generate-auth (don't forget to set req.session.authenticated somewhere in api/policies/passport.js). This might not be the best code, this is how I do it:

    file api/policies/passport.js:
    module.exports = function (req, res, next) {
    // Initialize Passport
    passport.initialize()(req, res, function () {
    // Use the built-in sessions
    passport.session()(req, res, function () {
    //passport.authenticate('session')(req, res, function () {
    // Make the user available throughout the frontend
    console.log("passport.session called, user is ", req.user);
    res.locals.user = req.user;
    if (typeof req.user != 'undefined') req.session.authenticated = true;
    else req.session.authenticated = false;
    next();
    });
    });
    };

    Reply
    Narendra - January 11, 2015

    Do follow this blog -
    There is much much easy way to do

    waterlock.ninja

    Reply
    Alejandro Ventura - December 7, 2015

    How to combine Passport with JWT in order to have authentication by tokens in SailsJS?

    Reply
    Giri - March 8, 2016

    In step 3, it should be
    `sails generate controller Auth` instead of `sails generate controller`

    Reply

Leave a Comment

Notify me of followup comments via e-mail

Get Adobe Flash player