/** * Module dependencies. */ var IncomingMessageExt = require('../http/request'); /** * Passport initialization. * * Intializes Passport for incoming requests, allowing authentication strategies * to be applied. * * If sessions are being utilized, applications must set up Passport with * functions to serialize a user into and out of a session. For example, a * common pattern is to serialize just the user ID into the session (due to the * fact that it is desirable to store the minimum amount of data in a session). * When a subsequent request arrives for the session, the full User object can * be loaded from the database by ID. * * Note that additional middleware is required to persist login state, so we * must use the `connect.session()` middleware _before_ `passport.initialize()`. * * If sessions are being used, this middleware must be in use by the * Connect/Express application for Passport to operate. If the application is * entirely stateless (not using sessions), this middleware is not necessary, * but its use will not have any adverse impact. * * Examples: * * app.use(connect.cookieParser()); * app.use(connect.session({ secret: 'keyboard cat' })); * app.use(passport.initialize()); * app.use(passport.session()); * * passport.serializeUser(function(user, done) { * done(null, user.id); * }); * * passport.deserializeUser(function(id, done) { * User.findById(id, function (err, user) { * done(err, user); * }); * }); * * @return {Function} * @api public */ module.exports = function initialize(passport, options) { options = options || {}; return function initialize(req, res, next) { req.login = req.logIn = req.logIn || IncomingMessageExt.logIn; req.logout = req.logOut = req.logOut || IncomingMessageExt.logOut; req.isAuthenticated = req.isAuthenticated || IncomingMessageExt.isAuthenticated; req.isUnauthenticated = req.isUnauthenticated || IncomingMessageExt.isUnauthenticated; req._sessionManager = passport._sm; if (options.userProperty) { req._userProperty = options.userProperty; } var compat = (options.compat === undefined) ? true : options.compat; if (compat) { // `passport@0.5.1` [removed][1] all internal use of `req._passport`. // From the standpoint of this package, this should have been a // non-breaking change. However, some strategies (such as `passport-azure-ad`) // depend directly on `passport@0.4.x` or earlier. `require`-ing earlier // versions of `passport` has the effect of monkeypatching `http.IncomingMessage` // with `logIn`, `logOut`, `isAuthenticated` and `isUnauthenticated` // functions that [expect][2] the `req._passport` property to exist. // Since pre-existing functions on `req` are given [preference][3], this // results in [issues][4]. // // The changes here restore the expected properties needed when earlier // versions of `passport` are `require`-ed. This compatibility mode is // enabled by default, and can be disabld by simply not `use`-ing `passport.initialize()` // middleware or setting `compat: false` as an option to the middleware. // // An alternative approach to addressing this issue would be to not // preferentially use pre-existing functions on `req`, but rather always // overwrite `req.logIn`, etc. with the versions of those functions shiped // with `authenticate()` middleware. This option should be reconsidered // in a future major version release. // // [1]: https://github.com/jaredhanson/passport/pull/875 // [2]: https://github.com/jaredhanson/passport/blob/v0.4.1/lib/http/request.js // [3]: https://github.com/jaredhanson/passport/blob/v0.5.1/lib/middleware/authenticate.js#L96 // [4]: https://github.com/jaredhanson/passport/issues/877 passport._userProperty = options.userProperty || 'user'; req._passport = {}; req._passport.instance = passport; } next(); }; };