pax_global_header00006660000000000000000000000064121440464060014513gustar00rootroot0000000000000052 comment=124a6d798438f4212e93ef19f8136a044ed85390 passport-0.1.17/000077500000000000000000000000001214404640600134545ustar00rootroot00000000000000passport-0.1.17/.gitignore000066400000000000000000000000731214404640600154440ustar00rootroot00000000000000# Mac OS X .DS_Store # Node.js node_modules npm-debug.log passport-0.1.17/.npmignore000066400000000000000000000001751214404640600154560ustar00rootroot00000000000000README.md Makefile doc/ examples/ test/ # Mac OS X .DS_Store # Node.js .npmignore node_modules/ npm-debug.log # Git .git* passport-0.1.17/.travis.yml000066400000000000000000000000651214404640600155660ustar00rootroot00000000000000language: "node_js" node_js: - 0.4 - 0.6 - 0.8 passport-0.1.17/LICENSE000066400000000000000000000020701214404640600144600ustar00rootroot00000000000000(The MIT License) Copyright (c) 2011-2013 Jared Hanson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. passport-0.1.17/Makefile000066400000000000000000000011521214404640600151130ustar00rootroot00000000000000SOURCES = lib/**/*.js # ============================================================================== # Node Tests # ============================================================================== VOWS = ./node_modules/.bin/vows TESTS ?= test/*-test.js test/**/*-test.js test/context/http/*-test.js test: @NODE_ENV=test NODE_PATH=lib $(VOWS) $(TESTS) # ============================================================================== # Static Analysis # ============================================================================== JSHINT = jshint hint: lint lint: $(JSHINT) $(SOURCES) .PHONY: test hint lint passport-0.1.17/README.md000066400000000000000000000135301214404640600147350ustar00rootroot00000000000000# Passport Passport is [Express](http://expressjs.com/)-compatible authentication middleware for [Node.js](http://nodejs.org/). Passport's sole purpose is to authenticate requests, which it does through an extensible set of plugins known as _strategies_. Passport does not mount routes or assume any particular database schema, which maximizes flexiblity and allows application-level decisions to be made by the developer. The API is simple: you provide Passport a request to authenticate, and Passport provides hooks for controlling what occurs when authentication succeeds or fails. ## Install $ npm install passport ## Usage #### Strategies Passport uses the concept of strategies to authenticate requests. Strategies can range from verifying username and password credentials, delegated authentication using [OAuth](http://oauth.net/) (for example, via [Facebook](http://www.facebook.com/) or [Twitter](http://twitter.com/)), or federated authentication using [OpenID](http://openid.net/). Before authenticating requests, the strategy (or strategies) used by an application must be configured. passport.use(new LocalStrategy( function(username, password, done) { User.findOne({ username: username, password: password }, function (err, user) { done(err, user); }); } )); #### Sessions Passport will maintain persistent login sessions. In order for persistent sessions to work, the authenticated user must be serialized to the session, and deserialized when subsequent requests are made. Passport does not impose any restrictions on how your user records are stored. Instead, you provide functions to Passport which implements the necessary serialization and deserialization logic. In a typical application, this will be as simple as serializing the user ID, and finding the user by ID when deserializing. passport.serializeUser(function(user, done) { done(null, user.id); }); passport.deserializeUser(function(id, done) { User.findById(id, function (err, user) { done(err, user); }); }); #### Middleware To use Passport in an [Express](http://expressjs.com/) or [Connect](http://senchalabs.github.com/connect/)-based application, configure it with the required `passport.initialize()` middleware. If your application uses persistent login sessions (recommended, but not required), `passport.session()` middleware must also be used. app.configure(function() { app.use(express.static(__dirname + '/../../public')); app.use(express.cookieParser()); app.use(express.bodyParser()); app.use(express.session({ secret: 'keyboard cat' })); app.use(passport.initialize()); app.use(passport.session()); app.use(app.router); }); #### Authenticate Requests Passport provides an `authenticate()` function, which is used as route middleware to authenticate requests. app.post('/login', passport.authenticate('local', { failureRedirect: '/login' }), function(req, res) { res.redirect('/'); }); ## Examples For a complete, working example, refer to the [login example](https://github.com/jaredhanson/passport-local/tree/master/examples/login) included in [passport-local](https://github.com/jaredhanson/passport-local). ## Strategies Passport has a comprehensive set of **over 120** authentication strategies covering social networking, enterprise integration, API services, and more. The [complete list](https://github.com/jaredhanson/passport/wiki/Strategies) is available on the [wiki](https://github.com/jaredhanson/passport/wiki). The following table lists commonly used strategies: |Strategy | Protocol |Developer | |---------------------------------------------------------------|--------------------------|------------------------------------------------| |[Local](https://github.com/jaredhanson/passport-local) | HTML form |[Jared Hanson](https://github.com/jaredhanson) | |[OpenID](https://github.com/jaredhanson/passport-openid) | OpenID |[Jared Hanson](https://github.com/jaredhanson) | |[BrowserID](https://github.com/jaredhanson/passport-browserid) | BrowserID |[Jared Hanson](https://github.com/jaredhanson) | |[Facebook](https://github.com/jaredhanson/passport-facebook) | OAuth 2.0 |[Jared Hanson](https://github.com/jaredhanson) | |[Google](https://github.com/jaredhanson/passport-google) | OpenID |[Jared Hanson](https://github.com/jaredhanson) | |[Google](https://github.com/jaredhanson/passport-google-oauth) | OAuth / OAuth 2.0 |[Jared Hanson](https://github.com/jaredhanson) | |[Twitter](https://github.com/jaredhanson/passport-twitter) | OAuth |[Jared Hanson](https://github.com/jaredhanson) | ## Related Modules - [Locomotive](https://github.com/jaredhanson/locomotive) — Powerful MVC web framework - [OAuthorize](https://github.com/jaredhanson/oauthorize) — OAuth service provider toolkit - [OAuth2orize](https://github.com/jaredhanson/oauth2orize) — OAuth 2.0 authorization server toolkit - [connect-ensure-login](https://github.com/jaredhanson/connect-ensure-login) — middleware to ensure login sessions The [modules](https://github.com/jaredhanson/passport/wiki/Modules) page on the [wiki](https://github.com/jaredhanson/passport/wiki) lists other useful modules that build upon or integrate with Passport. ## Tests $ npm install --dev $ make test [![Build Status](https://secure.travis-ci.org/jaredhanson/passport.png)](http://travis-ci.org/jaredhanson/passport) ## Credits - [Jared Hanson](http://github.com/jaredhanson) ## License [The MIT License](http://opensource.org/licenses/MIT) Copyright (c) 2011-2013 Jared Hanson <[http://jaredhanson.net/](http://jaredhanson.net/)> passport-0.1.17/lib/000077500000000000000000000000001214404640600142225ustar00rootroot00000000000000passport-0.1.17/lib/passport/000077500000000000000000000000001214404640600160755ustar00rootroot00000000000000passport-0.1.17/lib/passport/context/000077500000000000000000000000001214404640600175615ustar00rootroot00000000000000passport-0.1.17/lib/passport/context/http/000077500000000000000000000000001214404640600205405ustar00rootroot00000000000000passport-0.1.17/lib/passport/context/http/actions.js000066400000000000000000000046521214404640600225450ustar00rootroot00000000000000/** * Export actions prototype for strategies operating within an HTTP context. */ var actions = module.exports = {}; /** * Authenticate `user`, with optional `info`. * * Strategies should call this function to successfully authenticate a user. * `user` should be an object supplied by the application after it has been * given an opportunity to verify credentials. `info` is an optional argument * containing additional user information. This is useful for third-party * authentication strategies to pass profile details. * * @param {Object} user * @param {Object} info * @api public */ actions.success = function(user, info) { this.delegate.success.apply(this, arguments); } /** * Fail authentication, with optional `challenge` and `status`, defaulting to * 401. * * Strategies should call this function to fail an authentication attempt. * * @param {String} challenge * @param {Number} status * @api public */ actions.fail = function(challenge, status) { this.delegate.fail.apply(this, arguments); } /** * Redirect to `url` with optional `status`, defaulting to 302. * * Strategies should call this function to redirect the user (via their user * agent) to a third-party website for authentication. * * @param {String} url * @param {Number} status * @api public */ actions.redirect = function(url, status) { var res = this.res; if (typeof res.redirect == 'function') { // If possible use redirect method on the response // Assume Express API, optional status param comes first if (status) { res.redirect(status, url); } else { res.redirect(url); } } else { // Otherwise fall back to native methods res.statusCode = status || 302; res.setHeader('Location', url); res.setHeader('Content-Length', '0'); res.end(); } } /** * Pass without making a success or fail decision. * * Under most circumstances, Strategies should not need to call this function. * It exists primarily to allow previous authentication state to be restored, * for example from an HTTP session. * * @api public */ actions.pass = function() { this.next(); } /** * Internal error while performing authentication. * * Strategies should call this function when an internal error occurs during the * process of performing authentication; for example, if the user directory is * not available. * * @param {Error} err * @api public */ actions.error = function(err) { this.next(err); } passport-0.1.17/lib/passport/context/http/context.js000066400000000000000000000003611214404640600225620ustar00rootroot00000000000000/** * `Context` constructor. * * @api private */ function Context(delegate, req, res, next) { this.delegate = delegate; this.req = req; this.res = res; this.next = next; } /** * Expose `Context`. */ module.exports = Context; passport-0.1.17/lib/passport/http/000077500000000000000000000000001214404640600170545ustar00rootroot00000000000000passport-0.1.17/lib/passport/http/request.js000066400000000000000000000037251214404640600211110ustar00rootroot00000000000000/** * Module dependencies. */ var http = require('http') , req = http.IncomingMessage.prototype; /** * Intiate a login session for `user`. * * Options: * - `session` Save login state in session, defaults to _true_ * * Examples: * * req.logIn(user, { session: false }); * * req.logIn(user, function(err) { * if (err) { throw err; } * // session saved * }); * * @param {User} user * @param {Object} options * @param {Function} done * @api public */ req.login = req.logIn = function(user, options, done) { if (!this._passport) throw new Error('passport.initialize() middleware not in use'); if (!done && typeof options === 'function') { done = options; options = {}; } options = options || {}; var property = this._passport.instance._userProperty || 'user'; var session = (options.session === undefined) ? true : options.session; this[property] = user; if (session) { var self = this; this._passport.instance.serializeUser(user, function(err, obj) { if (err) { self[property] = null; return done(err); } self._passport.session.user = obj; done(); }); } else { done && done(); } } /** * Terminate an existing login session. * * @api public */ req.logout = req.logOut = function() { if (!this._passport) throw new Error('passport.initialize() middleware not in use'); var property = this._passport.instance._userProperty || 'user'; this[property] = null; delete this._passport.session.user; }; /** * Test if request is authenticated. * * @return {Boolean} * @api public */ req.isAuthenticated = function() { var property = 'user'; if (this._passport && this._passport.instance._userProperty) { property = this._passport.instance._userProperty; } return (this[property]) ? true : false; }; /** * Test if request is unauthenticated. * * @return {Boolean} * @api public */ req.isUnauthenticated = function() { return !this.isAuthenticated(); }; passport-0.1.17/lib/passport/index.js000066400000000000000000000312711214404640600175460ustar00rootroot00000000000000/** * Module dependencies. */ var fs = require('fs') , path = require('path') , util = require('util') , Strategy = require('./strategy') , SessionStrategy = require('./strategies/session') , initialize = require('./middleware/initialize') , authenticate = require('./middleware/authenticate'); /** * `Passport` constructor. * * @api public */ function Passport() { this._key = 'passport'; this._strategies = {}; this._serializers = []; this._deserializers = []; this._infoTransformers = []; this._framework = null; this._userProperty = 'user'; this.use(new SessionStrategy()); }; /** * Utilize the given `strategy` with optional `name`, overridding the strategy's * default name. * * Examples: * * passport.use(new TwitterStrategy(...)); * * passport.use('api', new http.BasicStrategy(...)); * * @param {String|Strategy} name * @param {Strategy} strategy * @return {Passport} for chaining * @api public */ Passport.prototype.use = function(name, strategy) { if (!strategy) { strategy = name; name = strategy.name; } if (!name) throw new Error('authentication strategies must have a name'); this._strategies[name] = strategy; return this; }; /** * Un-utilize the `strategy` with given `name`. * * In typical applications, the necessary authentication strategies are static, * configured once and always available. As such, there is often no need to * invoke this function. * * However, in certain situations, applications may need dynamically configure * and de-configure authentication strategies. The `use()`/`unuse()` * combination satisfies these scenarios. * * Examples: * * passport.unuse('legacy-api'); * * @param {String} name * @return {Passport} for chaining * @api public */ Passport.prototype.unuse = function(name) { delete this._strategies[name]; return this; } /** * Setup Passport to be used under framework. * * By default, Passport exposes middleware that operate using Connect-style * middleware using a `fn(req, res, next)` signature. Other popular frameworks * have different expectations, and this function allows Passport to be adapted * to operate within such environments. * * If you are using a Connect-compatible framework, including Express, there is * no need to invoke this function. * * Examples: * * passport.framework(require('hapi-passport')()); * * @param {Object} name * @return {Passport} for chaining * @api public */ Passport.prototype.framework = function(fw) { this._framework = fw; return this; } /** * Passport's primary initialization middleware. * * This middleware must be in use by the Connect/Express application for * Passport to operate. * * Options: * - `userProperty` Property to set on `req` upon login, defaults to _user_ * * Examples: * * app.configure(function() { * app.use(passport.initialize()); * }); * * app.configure(function() { * app.use(passport.initialize({ userProperty: 'currentUser' })); * }); * * @param {Object} options * @return {Function} middleware * @api public */ Passport.prototype.initialize = function(options) { options = options || {}; this._userProperty = options.userProperty || 'user'; if (this._framework && this._framework.initialize) { return this._framework.initialize().bind(this); } return initialize().bind(this); } /** * Middleware that will restore login state from a session. * * Web applications typically use sessions to maintain login state between * requests. For example, a user will authenticate by entering credentials into * a form which is submitted to the server. If the credentials are valid, a * login session is established by setting a cookie containing a session * identifier in the user's web browser. The web browser will send this cookie * in subsequent requests to the server, allowing a session to be maintained. * * If sessions are being utilized, and a login session has been established, * this middleware will populate `req.user` with the current user. * * Note that sessions are not strictly required for Passport to operate. * However, as a general rule, most web applications will make use of sessions. * An exception to this rule would be an API server, which expects each HTTP * request to provide credentials in an Authorization header. * * Examples: * * app.configure(function() { * app.use(connect.cookieParser()); * app.use(connect.session({ secret: 'keyboard cat' })); * app.use(passport.initialize()); * app.use(passport.session()); * }); * * Options: * - `pauseStream` Pause the request stream before deserializing the user * object from the session. Defaults to _false_. Should * be set to true in cases where middleware consuming the * request body is configured after passport and the * deserializeUser method is asynchronous. * * @param {Object} options * @return {Function} middleware * @api public */ Passport.prototype.session = function(options) { return this.authenticate('session', options); } /** * Middleware that will authenticate a request using the given `strategy` name, * with optional `options` and `callback`. * * Examples: * * passport.authenticate('local', { successRedirect: '/', failureRedirect: '/login' })(req, res); * * passport.authenticate('local', function(err, user) { * if (!user) { return res.redirect('/login'); } * res.end('Authenticated!'); * })(req, res); * * passport.authenticate('basic', { session: false })(req, res); * * app.get('/auth/twitter', passport.authenticate('twitter'), function(req, res) { * // request will be redirected to Twitter * }); * app.get('/auth/twitter/callback', passport.authenticate('twitter'), function(req, res) { * res.json(req.user); * }); * * @param {String} strategy * @param {Object} options * @param {Function} callback * @return {Function} middleware * @api public */ Passport.prototype.authenticate = function(strategy, options, callback) { if (this._framework && this._framework.authenticate) { return this._framework.authenticate(strategy, options, callback).bind(this); } return authenticate(strategy, options, callback).bind(this); } /** * Middleware that will authorize a third-party account using the given * `strategy` name, with optional `options`. * * If authorization is successful, the result provided by the strategy's verify * callback will be assigned to `req.account`. The existing login session and * `req.user` will be unaffected. * * This function is particularly useful when connecting third-party accounts * to the local account of a user that is currently authenticated. * * Examples: * * passport.authorize('twitter-authz', { failureRedirect: '/account' }); * * @param {String} strategy * @param {Object} options * @return {Function} middleware * @api public */ Passport.prototype.authorize = function(strategy, options, callback) { options = options || {}; options.assignProperty = 'account'; return authenticate(strategy, options, callback).bind(this); } /** * Registers a function used to serialize user objects into the session. * * Examples: * * passport.serializeUser(function(user, done) { * done(null, user.id); * }); * * @api public */ Passport.prototype.serializeUser = function(fn, done) { if (typeof fn === 'function') { return this._serializers.push(fn); } // private implementation that traverses the chain of serializers, attempting // to serialize a user var user = fn; var stack = this._serializers; (function pass(i, err, obj) { // serializers use 'pass' as an error to skip processing if ('pass' === err) { err = undefined; } // an error or serialized object was obtained, done if (err || obj || obj === 0) { return done(err, obj); } var layer = stack[i]; if (!layer) { return done(new Error('failed to serialize user into session')); } try { layer(user, function(e, o) { pass(i + 1, e, o); } ) } catch(e) { return done(e); } })(0); } /** * Registers a function used to deserialize user objects out of the session. * * Examples: * * passport.deserializeUser(function(id, done) { * User.findById(id, function (err, user) { * done(err, user); * }); * }); * * @api public */ Passport.prototype.deserializeUser = function(fn, done) { if (typeof fn === 'function') { return this._deserializers.push(fn); } // private implementation that traverses the chain of deserializers, // attempting to deserialize a user var obj = fn; var stack = this._deserializers; (function pass(i, err, user) { // deserializers use 'pass' as an error to skip processing if ('pass' === err) { err = undefined; } // an error or deserialized user was obtained, done if (err || user) { return done(err, user); } // a valid user existed when establishing the session, but that user has // since been removed if (user === null || user === false) { return done(null, false); } var layer = stack[i]; if (!layer) { return done(new Error('failed to deserialize user out of session')); } try { layer(obj, function(e, u) { pass(i + 1, e, u); } ) } catch(e) { return done(e); } })(0); } /** * Registers a function used to transform auth info. * * In some circumstances authorization details are contained in authentication * credentials or loaded as part of verification. * * For example, when using bearer tokens for API authentication, the tokens may * encode (either directly or indirectly in a database), details such as scope * of access or the client to which the token was issued. * * Such authorization details should be enforced separately from authentication. * Because Passport deals only with the latter, this is the responsiblity of * middleware or routes further along the chain. However, it is not optimal to * decode the same data or execute the same database query later. To avoid * this, Passport accepts optional `info` along with the authenticated `user` * in a strategy's `success()` action. This info is set at `req.authInfo`, * where said later middlware or routes can access it. * * Optionally, applications can register transforms to proccess this info, * which take effect prior to `req.authInfo` being set. This is useful, for * example, when the info contains a client ID. The transform can load the * client from the database and include the instance in the transformed info, * allowing the full set of client properties to be convieniently accessed. * * If no transforms are registered, `info` supplied by the strategy will be left * unmodified. * * Examples: * * passport.transformAuthInfo(function(info, done) { * Client.findById(info.clientID, function (err, client) { * info.client = client; * done(err, info); * }); * }); * * @api public */ Passport.prototype.transformAuthInfo = function(fn, done) { if (typeof fn === 'function') { return this._infoTransformers.push(fn); } // private implementation that traverses the chain of transformers, // attempting to transform auth info var info = fn; var stack = this._infoTransformers; (function pass(i, err, tinfo) { // transformers use 'pass' as an error to skip processing if ('pass' === err) { err = undefined; } // an error or transformed info was obtained, done if (err || tinfo) { return done(err, tinfo); } var layer = stack[i]; if (!layer) { // if no transformers are registered (or they all pass), the default // behavior is to use the un-transformed info as-is return done(null, info); } try { var arity = layer.length; if (arity == 1) { // sync var t = layer(info); pass(i + 1, null, t); } else { // async layer(info, function(e, t) { pass(i + 1, e, t); } ) } } catch(e) { return done(e); } })(0); } /** * Return strategy with given `name`. * * @param {String} name * @return {Strategy} * @api private */ Passport.prototype._strategy = function(name) { return this._strategies[name]; } /** * Export default singleton. * * @api public */ exports = module.exports = new Passport(); /** * Framework version. */ require('pkginfo')(module, 'version'); /** * Expose constructors. */ exports.Passport = Passport; exports.Strategy = Strategy; /** * Expose strategies. */ exports.strategies = {}; exports.strategies.SessionStrategy = SessionStrategy; /** * HTTP extensions. */ require('./http/request');passport-0.1.17/lib/passport/middleware/000077500000000000000000000000001214404640600202125ustar00rootroot00000000000000passport-0.1.17/lib/passport/middleware/authenticate.js000066400000000000000000000214051214404640600232300ustar00rootroot00000000000000/** * Module dependencies. */ var util = require('util') , actions = require('../context/http/actions') , Context = require('../context/http/context') /** * Authenticates requests. * * Applies the `name`ed strategy (or strategies) to the incoming request, in * order to authenticate the request. If authentication is successful, the user * will be logged in and populated at `req.user` and a session will be * established by default. If authentication fails, an unauthorized response * will be sent. * * Options: * - `session` Save login state in session, defaults to _true_ * - `successRedirect` After successful login, redirect to given URL * - `failureRedirect` After failed login, redirect to given URL * - `assignProperty` Assign the object provided by the verify callback to given property * * An optional `callback` can be supplied to allow the application to overrride * the default manner in which authentication attempts are handled. The * callback has the following signature, where `user` will be set to the * authenticated user on a successful authentication attempt, or `false` * otherwise. An optional `info` argument will be passed, containing additional * details provided by the strategy's verify callback. * * app.get('/protected', function(req, res, next) { * passport.authenticate('local', function(err, user, info) { * if (err) { return next(err) } * if (!user) { return res.redirect('/signin') } * res.redirect('/account'); * })(req, res, next); * }); * * Note that if a callback is supplied, it becomes the application's * responsibility to log-in the user, establish a session, and otherwise perform * the desired operations. * * Examples: * * passport.authenticate('local', { successRedirect: '/', failureRedirect: '/login' }); * * passport.authenticate('basic', { session: false }); * * passport.authenticate('twitter'); * * @param {String} name * @param {Object} options * @param {Function} callback * @return {Function} * @api public */ module.exports = function authenticate(name, options, callback) { if (!callback && typeof options === 'function') { callback = options; options = {}; } options = options || {}; // Cast `name` to an array, allowing authentication to pass through a chain of // strategies. The first strategy to succeed, redirect, or error will halt // the chain. Authentication failures will proceed through each strategy in // series, ultimately failing if all strategies fail. // // This is typically used on API endpoints to allow clients to authenticate // using their preferred choice of Basic, Digest, token-based schemes, etc. // It is not feasible to construct a chain of multiple strategies that involve // redirection (for example both Facebook and Twitter), since the first one to // redirect will halt the chain. if (!Array.isArray(name)) { name = [ name ]; } return function authenticate(req, res, next) { var passport = this; // accumulator for failures from each strategy in the chain var failures = []; function allFailed() { if (callback) { if (failures.length == 1) { return callback(null, false, failures[0].challenge, failures[0].status); } else { var challenges = failures.map(function(f) { return f.challenge; }); var statuses = failures.map(function(f) { return f.status; }) return callback(null, false, challenges, statuses); } } // Strategies are ordered by priority. For the purpose of flashing a // message, the first failure will be displayed. var failure = failures[0] || {} , challenge = failure.challenge || {}; if (options.failureFlash) { var flash = options.failureFlash; if (typeof flash == 'string') { flash = { type: 'error', message: flash }; } flash.type = flash.type || 'error'; var type = flash.type || challenge.type || 'error'; var msg = flash.message || challenge.message || challenge; if (typeof msg == 'string') { req.flash(type, msg); } } if (options.failureMessage) { var msg = options.failureMessage; if (typeof msg == 'boolean') { msg = challenge.message || challenge; } if (typeof msg == 'string') { req.session.messages = req.session.messages || []; req.session.messages.push(msg); } } if (options.failureRedirect) { return res.redirect(options.failureRedirect); } // When failure handling is not delegated to the application, the default // is to respond with 401 Unauthorized. Note that the WWW-Authenticate // header will be set according to the strategies in use (see // actions#fail). If multiple strategies failed, each of their challenges // will be included in the response. var rchallenge = [] , rstatus; for (var j = 0, len = failures.length; j < len; j++) { var failure = failures[j] , challenge = failure.challenge || {} , status = failure.status; if (typeof challenge == 'number') { status = challenge; challenge = null; } rstatus = rstatus || status; if (typeof challenge == 'string') { rchallenge.push(challenge) } } res.statusCode = rstatus || 401; if (rchallenge.length) { res.setHeader('WWW-Authenticate', rchallenge); } res.end('Unauthorized'); } (function attempt(i) { var delegate = {}; delegate.success = function(user, info) { if (callback) { return callback(null, user, info); } info = info || {} if (options.successFlash) { var flash = options.successFlash; if (typeof flash == 'string') { flash = { type: 'success', message: flash }; } flash.type = flash.type || 'success'; var type = flash.type || info.type || 'success'; var msg = flash.message || info.message || info; if (typeof msg == 'string') { req.flash(type, msg); } } if (options.successMessage) { var msg = options.successMessage; if (typeof msg == 'boolean') { msg = info.message || info; } if (typeof msg == 'string') { req.session.messages = req.session.messages || []; req.session.messages.push(msg); } } if (options.assignProperty) { req[options.assignProperty] = user; return next(); } req.logIn(user, options, function(err) { if (err) { return next(err); } if (options.authInfo || options.authInfo === undefined) { passport.transformAuthInfo(info, function(err, tinfo) { if (err) { return next(err); } req.authInfo = tinfo; complete(); }); } else { complete(); } function complete() { if (options.successReturnToOrRedirect) { var url = options.successReturnToOrRedirect; if (req.session && req.session.returnTo) { url = req.session.returnTo; delete req.session.returnTo; } return res.redirect(url); } if (options.successRedirect) { return res.redirect(options.successRedirect); } next(); } }); } delegate.fail = function(challenge, status) { // push this failure into the accumulator and attempt authentication // using the next strategy failures.push({ challenge: challenge, status: status }); attempt(i + 1); } var layer = name[i]; // If no more strategies exist in the chain, authentication has failed. if (!layer) { return allFailed(); } // Get the strategy, which will be used as prototype from which to create // a new instance. Action functions will then be bound to the strategy // within the context of the HTTP request/response pair. var prototype = passport._strategy(layer); if (!prototype) { return next(new Error('no strategy registered under name: ' + layer)); } var strategy = Object.create(prototype); var context = new Context(delegate, req, res, next); augment(strategy, actions, context); strategy.authenticate(req, options); })(0); // attempt } } function augment(strategy, actions, ctx) { for (var method in actions) { strategy[method] = actions[method].bind(ctx); } } passport-0.1.17/lib/passport/middleware/initialize.js000066400000000000000000000040661214404640600227170ustar00rootroot00000000000000/** * Module dependencies. */ var util = require('util'); /** * 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()`. * * This middleware must be in use by the Connect/Express application for * Passport to operate. * * Examples: * * app.configure(function() { * 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() { return function initialize(req, res, next) { var passport = this; req._passport = {}; req._passport.instance = passport; //console.log('!! session: ' + util.inspect(req.session)); if (req.session && req.session[passport._key]) { // load data from existing session req._passport.session = req.session[passport._key]; } else if (req.session) { // initialize new session req.session[passport._key] = {}; req._passport.session = req.session[passport._key]; } else { // no session is available req._passport.session = {}; } next(); } } passport-0.1.17/lib/passport/strategies/000077500000000000000000000000001214404640600202475ustar00rootroot00000000000000passport-0.1.17/lib/passport/strategies/session.js000066400000000000000000000035511214404640600222740ustar00rootroot00000000000000/** * Module dependencies. */ var pause = require('pause') , util = require('util') , Strategy = require('../strategy'); /** * `SessionStrategy` constructor. * * @api protected */ function SessionStrategy() { Strategy.call(this); this.name = 'session'; } /** * Inherit from `Strategy`. */ util.inherits(SessionStrategy, Strategy); /** * Authenticate request based on the current session state. * * The session authentication strategy uses the session to restore any login * state across requests. If a login session has been established, `req.user` * will be populated with the current user. * * This strategy is registered automatically by Passport. * * @param {Object} req * @param {Object} options * @api protected */ SessionStrategy.prototype.authenticate = function(req, options) { if (!req._passport) { return this.error(new Error('passport.initialize() middleware not in use')); } options = options || {}; var self = this , su = req._passport.session.user; if (su || su === 0) { // NOTE: Stream pausing is desirable in the case where later middleware is // listening for events emitted from request. For discussion on the // matter, refer to: https://github.com/jaredhanson/passport/pull/106 var paused = options.pauseStream ? pause(req) : null; req._passport.instance.deserializeUser(su, function(err, user) { if (err) { return self.error(err); } if (!user) { delete req._passport.session.user; self.pass(); if (paused) { paused.resume(); } return; }; var property = req._passport.instance._userProperty || 'user'; req[property] = user; self.pass(); if (paused) { paused.resume(); } }); } else { self.pass(); } } /** * Expose `SessionStrategy`. */ module.exports = SessionStrategy; passport-0.1.17/lib/passport/strategy.js000066400000000000000000000010421214404640600202720ustar00rootroot00000000000000/** * Module dependencies. */ var util = require('util'); /** * `Strategy` constructor. * * @api public */ function Strategy() { } /** * Authenticate request. * * This function must be overridden by subclasses. In abstract form, it always * throws an exception. * * @param {Object} req * @param {Object} options * @api protected */ Strategy.prototype.authenticate = function(req, options) { throw new Error('Strategy#authenticate must be overridden by subclass'); } /** * Expose `Strategy`. */ module.exports = Strategy; passport-0.1.17/package.json000066400000000000000000000016541214404640600157500ustar00rootroot00000000000000{ "name": "passport", "version": "0.1.17", "description": "Simple, unobtrusive authentication for Node.js.", "keywords": ["express", "connect", "auth", "authn", "authentication"], "homepage": "http://passportjs.org/", "repository": { "type": "git", "url": "git://github.com/jaredhanson/passport.git" }, "bugs": { "url": "http://github.com/jaredhanson/passport/issues" }, "author": { "name": "Jared Hanson", "email": "jaredhanson@gmail.com", "url": "http://www.jaredhanson.net/" }, "licenses": [ { "type": "MIT", "url": "http://www.opensource.org/licenses/MIT" } ], "main": "./lib/passport", "dependencies": { "pkginfo": "0.2.x", "pause": "0.0.1" }, "devDependencies": { "vows": "0.6.x" }, "scripts": { "test": "NODE_PATH=lib node_modules/.bin/vows test/*-test.js test/**/*-test.js test/context/http/*-test.js" }, "engines": { "node": ">= 0.4.0" } } passport-0.1.17/test/000077500000000000000000000000001214404640600144335ustar00rootroot00000000000000passport-0.1.17/test/context/000077500000000000000000000000001214404640600161175ustar00rootroot00000000000000passport-0.1.17/test/context/http/000077500000000000000000000000001214404640600170765ustar00rootroot00000000000000passport-0.1.17/test/context/http/actions-test.js000066400000000000000000000143771214404640600220650ustar00rootroot00000000000000var vows = require('vows'); var assert = require('assert'); var util = require('util'); var actions = require('passport/context/http/actions'); vows.describe('actions').addBatch({ 'success': { topic: function() { var self = this; var context = {}; context.delegate = {}; context.delegate.success = function(user, info) { self.callback(null, user, info); } var success = actions.success.bind(context); process.nextTick(function () { success({ id: '1', username: 'jaredhanson' }, { location: 'Oakland, CA' }); }); }, 'should forward function call to delegate': function (err, user, info) { assert.equal(user.id, '1'); assert.equal(user.username, 'jaredhanson'); assert.equal(info.location, 'Oakland, CA'); }, }, 'fail': { topic: function() { var self = this; var context = {}; context.delegate = {}; context.delegate.fail = function(challenge) { self.callback(null, challenge); } var fail = actions.fail.bind(context); process.nextTick(function () { fail('Basic realm="Users"'); }); }, 'should forward function call to delegate': function (err, challenge) { assert.equal(challenge, 'Basic realm="Users"'); }, }, 'fail with status code': { topic: function() { var self = this; var context = {}; context.delegate = {}; context.delegate.fail = function(challenge) { self.callback(null, challenge); } var fail = actions.fail.bind(context); process.nextTick(function () { fail(400); }); }, 'should forward function call to delegate': function (err, challenge) { assert.equal(challenge, 400); }, }, 'fail with challenge and status code': { topic: function() { var self = this; var context = {}; context.delegate = {}; context.delegate.fail = function(challenge, code) { self.callback(null, challenge, code); } var fail = actions.fail.bind(context); process.nextTick(function () { fail('Basic realm="Users"', 400); }); }, 'should forward function call to delegate': function (err, challenge, code) { assert.equal(challenge, 'Basic realm="Users"'); assert.equal(code, 400); }, }, 'redirect': { topic: function() { var self = this; var mockRes = {}; mockRes.setHeader = function(field, value) { this.header = this.header || {}; this.header[field] = value; } mockRes.end = function() { self.callback(null, this); } var context = {}; context.res = mockRes; var redirect = actions.redirect.bind(context); process.nextTick(function () { redirect('http://www.example.com/login'); }); }, 'should redirect to url': function (err, res) { assert.equal(res.statusCode, 302); assert.equal(res.header['Location'], 'http://www.example.com/login'); assert.equal(res.header['Content-Length'], '0'); }, }, 'redirect with status code': { topic: function() { var self = this; var mockRes = {}; mockRes.setHeader = function(field, value) { this.header = this.header || {}; this.header[field] = value; } mockRes.end = function() { self.callback(null, this); } var context = {}; context.res = mockRes; var redirect = actions.redirect.bind(context); process.nextTick(function () { redirect('http://www.example.com/login', 303); }); }, 'should redirect to url': function (err, res) { assert.equal(res.statusCode, 303); assert.equal(res.header['Location'], 'http://www.example.com/login'); assert.equal(res.header['Content-Length'], '0'); }, }, 'redirect using framework function': { topic: function() { var self = this; var mockRes = {}; mockRes.redirect = function(status, url) { if (!url) { url = status; status = 302; } this.statusCode = status; this.header = 'Location: ' + url; self.callback(null, this); } var context = {}; context.res = mockRes; var redirect = actions.redirect.bind(context); process.nextTick(function () { redirect('http://www.example.com/login', 303); }); }, 'should redirect to url': function (err, res) { assert.equal(res.statusCode, 303); assert.equal(res.header, 'Location: http://www.example.com/login'); }, }, 'redirect with status code using framework function': { topic: function() { var self = this; var mockRes = {}; mockRes.redirect = function(status, url) { if (!url) { url = status; status = 302; } this.statusCode = status; this.header = 'Location: ' + url; self.callback(null, this); } var context = {}; context.res = mockRes; var redirect = actions.redirect.bind(context); process.nextTick(function () { redirect('http://www.example.com/login'); }); }, 'should redirect to url': function (err, res) { assert.equal(res.statusCode, 302); assert.equal(res.header, 'Location: http://www.example.com/login'); }, }, 'pass': { topic: function() { var self = this; var context = {}; context.next = function() { self.callback(null); } var pass = actions.pass.bind(context); process.nextTick(function () { pass(); }); }, 'should call next': function (err, ok) { assert.isTrue(true); }, }, 'error': { topic: function() { var self = this; var context = {}; context.next = function(err) { self.callback(null, err); } var error = actions.error.bind(context); process.nextTick(function () { error(new Error('something is wrong')); }); }, 'should call next with an error': function (err, e) { assert.instanceOf(e, Error); assert.equal(e.message, 'something is wrong'); }, }, }).export(module); passport-0.1.17/test/http/000077500000000000000000000000001214404640600154125ustar00rootroot00000000000000passport-0.1.17/test/http/request-test.js000066400000000000000000000262351214404640600204250ustar00rootroot00000000000000var vows = require('vows'); var assert = require('assert'); var http = require('http') var util = require('util'); require('passport/http/request'); vows.describe('HttpServerRequest').addBatch({ 'request': { topic: function() { return new http.IncomingMessage(); }, 'logIn should be aliased to login': function (req) { assert.strictEqual(req.logIn, req.login); }, 'logOut should be aliased to logout': function (req) { assert.strictEqual(req.logOut, req.logout); }, }, 'request to login with a session': { topic: function() { var self = this; var req = new http.IncomingMessage(); var user = { id: '1', username: 'root' }; req._passport = {}; req._passport.instance = {}; req._passport.session = {}; req._passport.instance.serializeUser = function(user, done) { done(null, user.id); } function logIn() { req.logIn(user, function(err) { self.callback(err, req); }) } process.nextTick(function () { logIn(); }); }, 'should not generate an error' : function(err, req) { assert.isNull(err); }, 'should be authenticated': function (err, req) { assert.isTrue(req.isAuthenticated()); }, 'user property should be available': function (err, req) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'root'); }, 'session user data should be set': function (err, req) { assert.equal(req._passport.session.user, '1'); }, }, 'request to login with a session using a custom user property': { topic: function() { var self = this; var req = new http.IncomingMessage(); var user = { id: '1', username: 'root' }; req._passport = {}; req._passport.instance = {}; req._passport.instance._userProperty = 'currentUser'; req._passport.session = {}; req._passport.instance.serializeUser = function(user, done) { done(null, user.id); } function logIn() { req.logIn(user, function(err) { self.callback(err, req); }) } process.nextTick(function () { logIn(); }); }, 'should not generate an error' : function(err, req) { assert.isNull(err); }, 'should be authenticated': function (err, req) { assert.isTrue(req.isAuthenticated()); }, 'currentUser property should be available': function (err, req) { assert.isObject(req.currentUser); assert.equal(req.currentUser.id, '1'); assert.equal(req.currentUser.username, 'root'); }, 'user property should not be available': function (err, req) { assert.isUndefined(req.user); }, 'session user data should be set': function (err, req) { assert.equal(req._passport.session.user, '1'); }, }, 'request to login with a session but a badly behaving user serializer': { topic: function() { var self = this; var req = new http.IncomingMessage(); var user = { id: '1', username: 'root' }; req._passport = {}; req._passport.instance = {}; req._passport.session = {}; req._passport.instance.serializeUser = function(user, done) { done(new Error('failed to serialize')); } function logIn() { req.logIn(user, function(err) { self.callback(err, req); }) } process.nextTick(function () { logIn(); }); }, 'should generate an error' : function(err, req) { assert.instanceOf(err, Error); }, 'should not be authenticated': function (err, req) { assert.isFalse(req.isAuthenticated()); }, 'user property should not be available': function (err, req) { assert.isNull(req.user); }, 'session user data should not be set': function (err, req) { assert.isUndefined(req._passport.session.user); }, }, 'request to login without a session': { topic: function() { var self = this; var req = new http.IncomingMessage(); var user = { id: '1', username: 'root' }; req._passport = {}; req._passport.instance = {}; req._passport.session = {}; function logIn() { req.logIn(user, { session: false }, function(err) { self.callback(err, req); }) } process.nextTick(function () { logIn(); }); }, 'should not generate an error' : function(err, req) { assert.isNull(err); }, 'should be authenticated': function (err, req) { assert.isTrue(req.isAuthenticated()); }, 'user property should be available': function (err, req) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'root'); }, 'session user data should not be set': function (err, req) { assert.isUndefined(req._passport.session.user); }, }, 'request to login without a session using a custom user property': { topic: function() { var self = this; var req = new http.IncomingMessage(); var user = { id: '1', username: 'root' }; req._passport = {}; req._passport.instance = {}; req._passport.instance._userProperty = 'currentUser'; req._passport.session = {}; function logIn() { req.logIn(user, { session: false }, function(err) { self.callback(err, req); }) } process.nextTick(function () { logIn(); }); }, 'should not generate an error' : function(err, req) { assert.isNull(err); }, 'should be authenticated': function (err, req) { assert.isTrue(req.isAuthenticated()); }, 'currentUser property should be available': function (err, req) { assert.isObject(req.currentUser); assert.equal(req.currentUser.id, '1'); assert.equal(req.currentUser.username, 'root'); }, 'user property should not be available': function (err, req) { assert.isUndefined(req.user); }, 'session user data should not be set': function (err, req) { assert.isUndefined(req._passport.session.user); }, }, 'request to login without a session and no callback': { topic: function() { var self = this; var req = new http.IncomingMessage(); var user = { id: '1', username: 'root' }; req._passport = {}; req._passport.instance = {}; req._passport.session = {}; function logIn() { req.logIn(user, { session: false }); self.callback(null, req); } process.nextTick(function () { logIn(); }); }, 'should not generate an error' : function(err, req) { assert.isNull(err); }, 'should be authenticated': function (err, req) { assert.isTrue(req.isAuthenticated()); }, 'user property should be available': function (err, req) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'root'); }, 'session user data should not be set': function (err, req) { assert.isUndefined(req._passport.session.user); }, }, 'request with a login session': { topic: function() { var req = new http.IncomingMessage(); req.user = { id: '1', username: 'root' }; req._passport = {}; req._passport.instance = {}; req._passport.session = {}; req._passport.session.user = '1'; return req; }, 'after being logged out': { topic: function(req) { req.logOut(); return req; }, 'should not be authenticated': function (req) { assert.isFalse(req.isAuthenticated()); }, 'user property should be null': function (req) { assert.isNull(req.user); }, 'session user data should be null': function (req) { assert.isUndefined(req._passport.session.user); }, }, }, 'request with a login session using a custom user property': { topic: function() { var req = new http.IncomingMessage(); req.currentUser = { id: '1', username: 'root' }; req._passport = {}; req._passport.instance = {}; req._passport.instance._userProperty = 'currentUser'; req._passport.session = {}; req._passport.session.user = '1'; return req; }, 'after being logged out': { topic: function(req) { req.logOut(); return req; }, 'should not be authenticated': function (req) { assert.isFalse(req.isAuthenticated()); }, 'user property should be null': function (req) { assert.isNull(req.currentUser); }, 'session user data should be null': function (req) { assert.isUndefined(req._passport.session.user); }, }, }, 'request with a user': { topic: function() { var req = new http.IncomingMessage(); req.user = { id: '1', username: 'root' }; return req; }, 'should be authenticated': function (req) { assert.isFunction(req.isAuthenticated); assert.isTrue(req.isAuthenticated()); }, 'should not be unauthenticated': function (req) { assert.isFunction(req.isUnauthenticated); assert.isFalse(req.isUnauthenticated()); }, }, 'request with a user stored in a custom user property': { topic: function() { var req = new http.IncomingMessage(); req._passport = {}; req._passport.instance = {}; req._passport.instance._userProperty = 'currentUser'; req.currentUser = { id: '1', username: 'root' }; return req; }, 'should be authenticated': function (req) { assert.isFunction(req.isAuthenticated); assert.isTrue(req.isAuthenticated()); }, 'should not be unauthenticated': function (req) { assert.isFunction(req.isUnauthenticated); assert.isFalse(req.isUnauthenticated()); }, }, 'request without a user': { topic: function() { var req = new http.IncomingMessage(); return req; }, 'should not be authenticated': function (req) { assert.isFunction(req.isAuthenticated); assert.isFalse(req.isAuthenticated()); }, 'should be unauthenticated': function (req) { assert.isFunction(req.isUnauthenticated); assert.isTrue(req.isUnauthenticated()); }, }, 'request with a null user': { topic: function() { var req = new http.IncomingMessage(); req.user = null; return req; }, 'should not be authenticated': function (req) { assert.isFunction(req.isAuthenticated); assert.isFalse(req.isAuthenticated()); }, 'should be unauthenticated': function (req) { assert.isFunction(req.isUnauthenticated); assert.isTrue(req.isUnauthenticated()); }, }, 'request without an internal passport instance': { topic: function() { return new http.IncomingMessage(); }, 'should throw an error when attempting to login': function (req) { assert.throws(function() { req.logIn(); }); }, 'should throw an error when attempting to logout': function (req) { assert.throws(function() { req.logOut(); }); }, }, }).export(module); passport-0.1.17/test/index-test.js000066400000000000000000000354631214404640600170700ustar00rootroot00000000000000var vows = require('vows'); var assert = require('assert'); var passport = require('passport'); var util = require('util'); var Passport = require('passport').Passport; vows.describe('passport').addBatch({ 'module': { 'should report a version': function (x) { assert.isString(passport.version); }, }, 'passport': { topic: function() { return new Passport(); }, 'should create initialization middleware': function (passport) { var initialize = passport.initialize(); assert.isFunction(initialize); assert.lengthOf(initialize, 3); }, 'should create session restoration middleware': function (passport) { var session = passport.session(); assert.isFunction(session); assert.lengthOf(session, 3); }, 'should create authentication middleware': function (passport) { var authenticate = passport.authenticate(); assert.isFunction(authenticate); assert.lengthOf(authenticate, 3); }, }, 'passport with strategies': { topic: function() { return new Passport(); }, 'should add strategies': function (passport) { var strategy = {}; strategy.name = 'default'; passport.use(strategy); assert.isObject(passport._strategies['default']); passport._strategies = {}; }, 'should add strategies with specified name': function (passport) { var strategy = {}; passport.use('foo', strategy); assert.isObject(passport._strategies['foo']); passport._strategies = {}; }, 'should add strategies that have a name with overrride name': function (passport) { var strategy = {}; strategy.name = 'foo'; passport.use('my-foo', strategy); assert.isObject(passport._strategies['my-foo']); assert.isUndefined(passport._strategies['foo']); passport._strategies = {}; }, 'should throw an error when adding strategies without a name' : function(passport) { var strategy = {}; assert.throws(function() { passport.use(strategy); }); }, }, 'passport with strategies to unuse': { topic: function() { return new Passport(); }, 'should unuse strategies': function (passport) { var strategyOne = {}; strategyOne.name = 'one'; passport.use(strategyOne); var strategyTwo = {}; strategyTwo.name = 'two'; passport.use(strategyTwo); // session is implicitly used assert.lengthOf(Object.keys(passport._strategies), 3); assert.isObject(passport._strategies['one']); assert.isObject(passport._strategies['two']); passport.unuse('one'); assert.lengthOf(Object.keys(passport._strategies), 2); assert.isUndefined(passport._strategies['one']); assert.isObject(passport._strategies['two']); }, }, 'passport with no serializers': { topic: function() { var self = this; var passport = new Passport(); function serialized(err, obj) { self.callback(err, obj); } process.nextTick(function () { passport.serializeUser({ id: '1', username: 'jared' }, serialized); }); }, 'should fail to serialize user': function (err, obj) { assert.instanceOf(err, Error); assert.isUndefined(obj); }, }, 'passport with one serializer': { topic: function() { var self = this; var passport = new Passport(); passport.serializeUser(function(user, done) { done(null, user.id); }); function serialized(err, obj) { self.callback(err, obj); } process.nextTick(function () { passport.serializeUser({ id: '1', username: 'jared' }, serialized); }); }, 'should serialize user': function (err, obj) { assert.isNull(err); assert.equal(obj, '1'); }, }, 'passport with multiple serializers': { topic: function() { var self = this; var passport = new Passport(); passport.serializeUser(function(user, done) { done('pass'); }); passport.serializeUser(function(user, done) { done(null, 'second-serializer'); }); passport.serializeUser(function(user, done) { done(null, 'should-not-execute'); }); function serialized(err, obj) { self.callback(err, obj); } process.nextTick(function () { passport.serializeUser({ id: '1', username: 'jared' }, serialized); }); }, 'should serialize user': function (err, obj) { assert.isNull(err); assert.equal(obj, 'second-serializer'); }, }, 'passport with one serializer that sets user to 0': { topic: function() { var self = this; var passport = new Passport(); passport.serializeUser(function(user, done) { done(null, 0); }); function serialized(err, obj) { self.callback(err, obj); } process.nextTick(function () { passport.serializeUser({ id: '1', username: 'jared' }, serialized); }); }, 'should serialize user': function (err, obj) { assert.isNull(err); assert.equal(obj, 0); }, }, 'passport with one serializer that sets user to null': { topic: function() { var self = this; var passport = new Passport(); passport.serializeUser(function(user, done) { done(null, null); }); function serialized(err, obj) { self.callback(err, obj); } process.nextTick(function () { passport.serializeUser({ id: '1', username: 'jared' }, serialized); }); }, 'should fail to serialize user': function (err, obj) { assert.instanceOf(err, Error); assert.isUndefined(obj); }, }, 'passport with one serializer that sets user to false': { topic: function() { var self = this; var passport = new Passport(); passport.serializeUser(function(user, done) { done(null, false); }); function serialized(err, obj) { self.callback(err, obj); } process.nextTick(function () { passport.serializeUser({ id: '1', username: 'jared' }, serialized); }); }, 'should fail to serialize user': function (err, obj) { assert.instanceOf(err, Error); assert.isUndefined(obj); }, }, 'passport with a serializer that throws an error': { topic: function() { var self = this; var passport = new Passport(); passport.serializeUser(function(user, done) { // throws ReferenceError: wtf is not defined wtf }); function serialized(err, obj) { self.callback(err, obj); } process.nextTick(function () { passport.serializeUser({ id: '1', username: 'jared' }, serialized); }); }, 'should fail to serialize user': function (err, obj) { assert.instanceOf(err, Error); assert.isUndefined(obj); }, }, 'passport with no deserializers': { topic: function() { var self = this; var passport = new Passport(); function deserialized(err, user) { self.callback(err, user); } process.nextTick(function () { passport.deserializeUser({ id: '1', username: 'jared' }, deserialized); }); }, 'should fail to deserialize user': function (err, user) { assert.instanceOf(err, Error); assert.isUndefined(user); }, }, 'passport with one deserializer': { topic: function() { var self = this; var passport = new Passport(); passport.deserializeUser(function(obj, done) { done(null, obj.username); }); function deserialized(err, user) { self.callback(err, user); } process.nextTick(function () { passport.deserializeUser({ id: '1', username: 'jared' }, deserialized); }); }, 'should deserialize user': function (err, user) { assert.isNull(err); assert.equal(user, 'jared'); }, }, 'passport with multiple deserializers': { topic: function() { var self = this; var passport = new Passport(); passport.deserializeUser(function(obj, done) { done('pass'); }); passport.deserializeUser(function(obj, done) { done(null, 'second-deserializer'); }); passport.deserializeUser(function(obj, done) { done(null, 'should-not-execute'); }); function deserialized(err, user) { self.callback(err, user); } process.nextTick(function () { passport.deserializeUser({ id: '1', username: 'jared' }, deserialized); }); }, 'should deserialize user': function (err, user) { assert.isNull(err); assert.equal(user, 'second-deserializer'); }, }, 'passport with one deserializer that sets user to null': { topic: function() { var self = this; var passport = new Passport(); passport.deserializeUser(function(obj, done) { done(null, null); }); function deserialized(err, user) { self.callback(err, user); } process.nextTick(function () { passport.deserializeUser({ id: '1', username: 'jared' }, deserialized); }); }, 'should invalidate user': function (err, user) { assert.isNull(err); assert.strictEqual(user, false); }, }, 'passport with one deserializer that sets user to false': { topic: function() { var self = this; var passport = new Passport(); passport.deserializeUser(function(obj, done) { done(null, false); }); function deserialized(err, user) { self.callback(err, user); } process.nextTick(function () { passport.deserializeUser({ id: '1', username: 'jared' }, deserialized); }); }, 'should invalidate user': function (err, user) { assert.isNull(err); assert.strictEqual(user, false); }, }, 'passport with multiple deserializers, the second of which sets user to null': { topic: function() { var self = this; var passport = new Passport(); passport.deserializeUser(function(obj, done) { done('pass'); }); passport.deserializeUser(function(obj, done) { done(null, null); }); passport.deserializeUser(function(obj, done) { done(null, 'should-not-execute'); }); function deserialized(err, user) { self.callback(err, user); } process.nextTick(function () { passport.deserializeUser({ id: '1', username: 'jared' }, deserialized); }); }, 'should invalidate user': function (err, user) { assert.isNull(err); assert.strictEqual(user, false); }, }, 'passport with multiple deserializers, the second of which sets user to false': { topic: function() { var self = this; var passport = new Passport(); passport.deserializeUser(function(obj, done) { done('pass'); }); passport.deserializeUser(function(obj, done) { done(null, false); }); passport.deserializeUser(function(obj, done) { done(null, 'should-not-execute'); }); function deserialized(err, user) { self.callback(err, user); } process.nextTick(function () { passport.deserializeUser({ id: '1', username: 'jared' }, deserialized); }); }, 'should invalidate user': function (err, user) { assert.isNull(err); assert.strictEqual(user, false); }, }, 'passport with a deserializer that throws an error': { topic: function() { var self = this; var passport = new Passport(); passport.deserializeUser(function(obj, done) { // throws ReferenceError: wtf is not defined wtf }); function deserialized(err, user) { self.callback(err, user); } process.nextTick(function () { passport.deserializeUser({ id: '1', username: 'jared' }, deserialized); }); }, 'should fail to deserialize user': function (err, obj) { assert.instanceOf(err, Error); assert.isUndefined(obj); }, }, 'passport with no auth info transformers': { topic: function() { var self = this; var passport = new Passport(); function transformed(err, obj) { self.callback(err, obj); } process.nextTick(function () { passport.transformAuthInfo({ clientId: '1', scope: 'write' }, transformed); }); }, 'should leave info untransformed': function (err, obj) { assert.isNull(err); assert.equal(obj.clientId, '1'); assert.equal(obj.scope, 'write'); }, }, 'passport with one auth info transformer': { topic: function() { var self = this; var passport = new Passport(); passport.transformAuthInfo(function(info, done) { done(null, { clientId: info.clientId, client: { name: 'foo' }}); }); function transformed(err, obj) { self.callback(err, obj); } process.nextTick(function () { passport.transformAuthInfo({ clientId: '1', scope: 'write' }, transformed); }); }, 'should transform info': function (err, obj) { assert.isNull(err); assert.equal(obj.clientId, '1'); assert.equal(obj.client.name, 'foo'); assert.isUndefined(obj.scope); }, }, 'passport with multiple auth info transformers': { topic: function() { var self = this; var passport = new Passport(); passport.transformAuthInfo(function(info, done) { done('pass'); }); passport.transformAuthInfo(function(info, done) { done(null, { clientId: info.clientId, client: { name: 'bar' }}); }); passport.transformAuthInfo(function(info, done) { done(null, { clientId: info.clientId, client: { name: 'not-bar' }}); }); function transformed(err, obj) { self.callback(err, obj); } process.nextTick(function () { passport.transformAuthInfo({ clientId: '1', scope: 'write' }, transformed); }); }, 'should transform info': function (err, obj) { assert.isNull(err); assert.equal(obj.clientId, '1'); assert.equal(obj.client.name, 'bar'); assert.isUndefined(obj.scope); }, }, 'passport with an auth info transformer that throws an error': { topic: function() { var self = this; var passport = new Passport(); passport.transformAuthInfo(function(user, done) { // throws ReferenceError: wtf is not defined wtf }); function transformed(err, obj) { self.callback(err, obj); } process.nextTick(function () { passport.serializeUser({ clientId: '1', scope: 'write' }, transformed); }); }, 'should fail to transform info': function (err, obj) { assert.instanceOf(err, Error); assert.isUndefined(obj); }, }, }).export(module); passport-0.1.17/test/middleware/000077500000000000000000000000001214404640600165505ustar00rootroot00000000000000passport-0.1.17/test/middleware/authenticate-test.js000066400000000000000000003531431214404640600225520ustar00rootroot00000000000000var vows = require('vows'); var assert = require('assert'); var passport = require('passport'); var util = require('util'); var Passport = require('passport').Passport; function MockSuccessStrategy() { } MockSuccessStrategy.prototype.authenticate = function(req, options) { var user = { id: '1', username: 'jaredhanson' }; if (options && options.scope && options.scope === 'email') { user.email = 'jaredhanson@example.com'; } this.success(user); } function MockSuccessInfoMessageStrategy() { } MockSuccessInfoMessageStrategy.prototype.authenticate = function(req) { var user = { id: '1', username: 'jaredhanson' }; this.success(user, { message: 'Welcome!' }); } function MockSuccessInfoTypeAndMessageStrategy() { } MockSuccessInfoTypeAndMessageStrategy.prototype.authenticate = function(req) { var user = { id: '1', username: 'jaredhanson' }; this.success(user, { type: 'info', message: 'Hello' }); } function MockSuccessStringMessageStrategy() { } MockSuccessStringMessageStrategy.prototype.authenticate = function(req) { var user = { id: '1', username: 'jaredhanson' }; this.success(user, 'Greetings'); } function MockSuccessTokenStrategy() { } MockSuccessTokenStrategy.prototype.authenticate = function(req) { var user = { id: '1', username: 'jaredhanson' }; this.success(user, { token: 'abcd', clientId: '123' }); } function MockFailureStrategy() { } MockFailureStrategy.prototype.authenticate = function(req) { this.fail(); } function MockFailureInfoMessageStrategy() { } MockFailureInfoMessageStrategy.prototype.authenticate = function(req) { this.fail({ message: 'Invalid password' }); } function MockFailureInfoTypeAndMessageStrategy() { } MockFailureInfoTypeAndMessageStrategy.prototype.authenticate = function(req) { this.fail({ type: 'notice', message: 'Invite required' }); } function MockFailureStringMessageStrategy() { } MockFailureStringMessageStrategy.prototype.authenticate = function(req) { this.fail('Access denied'); } function MockChallengeStrategy() { } MockChallengeStrategy.prototype.authenticate = function(req) { this.fail('Mock challenge'); } function MockForbiddenStrategy() { } MockForbiddenStrategy.prototype.authenticate = function(req) { this.fail('Mock challenge', 403); } function MockBadRequestStrategy() { } MockBadRequestStrategy.prototype.authenticate = function(req) { this.fail(400); } function MockLocalStrategy(options) { this.options = options || {}; } MockLocalStrategy.prototype.authenticate = function(req) { if (!this.options.fail) { this.success({ username: 'bob-local' }); } else { this.fail('Bad username or password'); } } function MockSingleUseTokenStrategy(options) { this.options = options || {}; } MockSingleUseTokenStrategy.prototype.authenticate = function(req) { if (!this.options.fail) { this.success({ username: 'bob-sut' }); } else { this.fail('Bad token'); } } function MockBasicStrategy(options) { this.options = options || {}; } MockBasicStrategy.prototype.authenticate = function(req) { if (!this.options.fail) { this.success({ username: 'bob-basic' }); } else { this.fail('Basic foo', this.options.statusCode); } } function MockDigestStrategy(options) { this.options = options || {}; } MockDigestStrategy.prototype.authenticate = function(req) { if (!this.options.fail) { this.success({ username: 'bob-digest' }); } else { this.fail('Digest foo', this.options.statusCode); } } function MockNoChallengeStrategy(options) { this.options = options || {}; } MockNoChallengeStrategy.prototype.authenticate = function(req) { if (!this.options.fail) { this.success({ username: 'bob-nc' }); } else { this.fail(this.options.statusCode); } } function MockRequest() { } MockRequest.prototype.logIn = function(user, options, done) { if (this.loginError) { done(new Error('login error')); } else { this.user = user; done(); } } function MockResponse() { this._headers = {}; } MockResponse.prototype.setHeader = function(name, value) { this._headers[name] = value; } vows.describe('authenticate').addBatch({ 'with a successful authentication': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessStrategy()); return passport.authenticate('success'); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); function next(err) { self.callback(err, req, res); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should not set email on user according to scope' : function(err, req, res) { assert.isUndefined(req.user.email); }, 'should have empty auth info' : function(err, req, res) { assert.isObject(req.authInfo); assert.lengthOf(Object.keys(req.authInfo), 0); }, }, }, 'with a successful authentication passing options to strategy': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessStrategy()); return passport.authenticate('success', { scope: 'email' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); function next(err) { self.callback(err, req, res); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set email on user according to scope' : function(err, req, res) { assert.equal(req.user.email, 'jaredhanson@example.com'); }, 'should have empty auth info' : function(err, req, res) { assert.isObject(req.authInfo); assert.lengthOf(Object.keys(req.authInfo), 0); }, }, }, 'with a successful authentication but failed login': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessStrategy()); return passport.authenticate('success'); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); req.loginError = true; var res = new MockResponse(); function next(err) { self.callback(err, req, res); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.instanceOf(err, Error); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should not set auth info on request' : function(err, req, res) { assert.isUndefined(req.authInfo); }, }, }, 'with a successful authentication and redirect option': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessStrategy); return passport.authenticate('success', { successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should have empty auth info' : function(err, req, res) { assert.isObject(req.authInfo); assert.lengthOf(Object.keys(req.authInfo), 0); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication and return to or redirect option': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessStrategy); return passport.authenticate('success', { successReturnToOrRedirect: 'http://www.example.com/default' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); req.session = { returnTo: 'http://www.example.com/return' } var res = new MockResponse(); res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/return'); }, 'should remove returnTo from session' : function(err, req, res) { assert.isUndefined(req.session.returnTo); }, }, }, 'with a successful authentication and return to or redirect option with no return to set in session': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessStrategy); return passport.authenticate('success', { successReturnToOrRedirect: 'http://www.example.com/default' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/default'); }, }, }, 'with a successful authentication containing token info and no transforms': { topic: function() { var self = this; var passport = new Passport(); passport.use('token', new MockSuccessTokenStrategy); return passport.authenticate('token'); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); function next(err) { self.callback(err, req, res); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set authInfo on request' : function(err, req, res) { assert.isObject(req.authInfo); assert.lengthOf(Object.keys(req.authInfo), 2); assert.equal(req.authInfo.token, 'abcd'); assert.equal(req.authInfo.clientId, '123'); }, }, }, 'with a successful authentication containing token info and a transform': { topic: function() { var self = this; var passport = new Passport(); passport.use('token', new MockSuccessTokenStrategy); passport.transformAuthInfo(function(info, done) { done(null, { clientId: info.clientId, client: { name: 'foo' }}); }); return passport.authenticate('token'); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); function next(err) { self.callback(err, req, res); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set authInfo on request' : function(err, req, res) { assert.isObject(req.authInfo); assert.lengthOf(Object.keys(req.authInfo), 2); assert.isUndefined(req.authInfo.token); assert.equal(req.authInfo.clientId, '123'); assert.equal(req.authInfo.client.name, 'foo'); }, }, }, 'with a successful authentication containing token info and a transform that errors': { topic: function() { var self = this; var passport = new Passport(); passport.use('token', new MockSuccessTokenStrategy); passport.transformAuthInfo(function(info, done) { done(new Error('something went wrong')); }); return passport.authenticate('token'); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); function next(err) { self.callback(err, req, res); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should generate an error' : function(err, req, res) { assert.instanceOf(err, Error); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should not set authInfo on request' : function(err, req, res) { assert.isUndefined(req.authInfo); }, }, }, 'with a successful authentication containing token info and authInfo option set to false': { topic: function() { var self = this; var passport = new Passport(); passport.use('token', new MockSuccessTokenStrategy); return passport.authenticate('token', { authInfo: false }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); function next(err) { self.callback(err, req, res); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should not set authInfo on request' : function(err, req, res) { assert.isUndefined(req.authInfo); }, }, }, 'with a successful authentication containing info message using string message option': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessInfoMessageStrategy); return passport.authenticate('success', { successMessage: 'Login complete', successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.session = {}; res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set message on request' : function(err, req, res) { assert.lengthOf(req.session.messages, 1); assert.equal(req.session.messages[0], 'Login complete'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication containing info message using string message option with existing messages': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessInfoMessageStrategy); return passport.authenticate('success', { successMessage: 'Login complete', successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.session = {}; req.session.messages = [ 'I exist!' ]; res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set message on request' : function(err, req, res) { assert.lengthOf(req.session.messages, 2); assert.equal(req.session.messages[0], 'I exist!'); assert.equal(req.session.messages[1], 'Login complete'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication containing info message using boolean message option': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessInfoMessageStrategy); return passport.authenticate('success', { successMessage: true, successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.session = {}; res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set message on request' : function(err, req, res) { assert.lengthOf(req.session.messages, 1); assert.equal(req.session.messages[0], 'Welcome!'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication containing info type and message using boolean message option': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessInfoTypeAndMessageStrategy); return passport.authenticate('success', { successMessage: true, successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.session = {}; res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set message on request' : function(err, req, res) { assert.lengthOf(req.session.messages, 1); assert.equal(req.session.messages[0], 'Hello'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication containing info message using boolean flash option': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessInfoMessageStrategy); return passport.authenticate('success', { successFlash: true, successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set message in auth info' : function(err, req, res) { assert.isObject(req.authInfo); assert.lengthOf(Object.keys(req.authInfo), 1); assert.equal(req.authInfo.message, 'Welcome!'); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'success'); assert.equal(req.message.msg, 'Welcome!'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication containing info message using string flash option': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessInfoMessageStrategy); return passport.authenticate('success', { successFlash: 'Login complete', successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'success'); assert.equal(req.message.msg, 'Login complete'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication containing info message using flash option': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessInfoMessageStrategy); return passport.authenticate('success', { successFlash: { type: 'notice', message: 'Last login was yesterday' }, successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'notice'); assert.equal(req.message.msg, 'Last login was yesterday'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication containing info message using flash option with message only': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessInfoMessageStrategy); return passport.authenticate('success', { successFlash: { message: 'OK' }, successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'success'); assert.equal(req.message.msg, 'OK'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication containing info message using flash option with type only': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessInfoMessageStrategy); return passport.authenticate('success', { successFlash: { type: 'info' }, successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'info'); assert.equal(req.message.msg, 'Welcome!'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication containing info type and message using boolean flash option': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessInfoTypeAndMessageStrategy); return passport.authenticate('success', { successFlash: true, successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'info'); assert.equal(req.message.msg, 'Hello'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication containing info type and message using string flash option': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessInfoTypeAndMessageStrategy); return passport.authenticate('success', { successFlash: 'Success!', successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'success'); assert.equal(req.message.msg, 'Success!'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication containing info type and message using flash option': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessInfoTypeAndMessageStrategy); return passport.authenticate('success', { successFlash: { type: 'warn', message: 'Last login from far away place' }, successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'warn'); assert.equal(req.message.msg, 'Last login from far away place'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication containing info type and message using flash option with message only': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessInfoTypeAndMessageStrategy); return passport.authenticate('success', { successFlash: { message: 'Okay' }, successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'success'); assert.equal(req.message.msg, 'Okay'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication containing info type and message using flash option with type only': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessInfoTypeAndMessageStrategy); return passport.authenticate('success', { successFlash: { type: 'ok' }, successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'ok'); assert.equal(req.message.msg, 'Hello'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication containing string message using boolean flash option': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessStringMessageStrategy); return passport.authenticate('success', { successFlash: true, successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'success'); assert.equal(req.message.msg, 'Greetings'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication containing string message using string flash option': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessStringMessageStrategy); return passport.authenticate('success', { successFlash: 'Login complete', successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'success'); assert.equal(req.message.msg, 'Login complete'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication containing string message using flash option': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessStringMessageStrategy); return passport.authenticate('success', { successFlash: { type: 'notice', message: 'Last login was yesterday' }, successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'notice'); assert.equal(req.message.msg, 'Last login was yesterday'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication containing string message using flash option with message only': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessStringMessageStrategy); return passport.authenticate('success', { successFlash: { message: 'OK' }, successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'success'); assert.equal(req.message.msg, 'OK'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication containing string message using flash option with type only': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessStringMessageStrategy); return passport.authenticate('success', { successFlash: { type: 'info' }, successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'info'); assert.equal(req.message.msg, 'Greetings'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication lacking info message using boolean flash option': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessStrategy); return passport.authenticate('success', { successFlash: true, successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should not set flash on request' : function(err, req, res) { assert.isUndefined(req.message); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication lacking info message using string flash option': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessStrategy); return passport.authenticate('success', { successFlash: 'Login complete', successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'success'); assert.equal(req.message.msg, 'Login complete'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication lacking info message using flash option': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessStrategy); return passport.authenticate('success', { successFlash: { type: 'notice', message: 'Last login was yesterday' }, successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'notice'); assert.equal(req.message.msg, 'Last login was yesterday'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication lacking info message using flash option with message only': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessStrategy); return passport.authenticate('success', { successFlash: { message: 'OK' }, successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'success'); assert.equal(req.message.msg, 'OK'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication lacking info message using flash option with type only': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessStrategy); return passport.authenticate('success', { successFlash: { type: 'info' }, successRedirect: 'http://www.example.com/account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.id, '1'); assert.equal(req.user.username, 'jaredhanson'); }, 'should not set flash on request' : function(err, req, res) { assert.isUndefined(req.message); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/account'); }, }, }, 'with a successful authentication and assignProperty option': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessStrategy); return passport.authenticate('success', { assignProperty: 'account' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); function next(err) { self.callback(err, req, res); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set account on request' : function(err, req, res) { assert.isObject(req.account); assert.equal(req.account.id, '1'); assert.equal(req.account.username, 'jaredhanson'); }, }, }, 'with a successful authentication and callback': { topic: function() { var self = this; var passport = new Passport(); passport.use('success', new MockSuccessInfoMessageStrategy); var callback = function(err, user, info) { this.done(err, user, info); } var context = {}; var authenticate = passport.authenticate('success', callback.bind(context)); process.nextTick(function () { self.callback(null, authenticate, context); }); }, 'when handling a request': { topic: function(authenticate, context) { var self = this; var req = new MockRequest(); var res = new MockResponse(); context.done = function(err, user, info) { self.callback(err, req, res, user, info); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res, user, info) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res, user, info) { assert.isUndefined(req.user); }, 'should pass user to callback' : function(err, req, res, user, info) { assert.isObject(user); assert.equal(user.id, '1'); assert.equal(user.username, 'jaredhanson'); }, 'should pass profile to callback' : function(err, req, res, user, info) { assert.isObject(info); assert.equal(info.message, 'Welcome!'); }, }, }, 'with a failed authentication': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureStrategy()); return passport.authenticate('failure'); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); res.end = function() { self.callback(null, req, res) } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set status code to unauthorized' : function(err, req, res) { assert.equal(res.statusCode, 401); }, }, }, 'with a failed authentication and redirect option': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureStrategy()); return passport.authenticate('failure', { failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a failed authentication and callback': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureStrategy()); var callback = function(err, user) { this.done(err, user); } var context = {}; var authenticate = passport.authenticate('failure', callback.bind(context)); process.nextTick(function () { self.callback(null, authenticate, context); }); }, 'when handling a request': { topic: function(authenticate, context) { var self = this; var req = new MockRequest(); var res = new MockResponse(); context.done = function(err, user) { self.callback(err, req, res, user); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res, user) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res, user) { assert.isUndefined(req.user); }, 'should pass user to callback as false' : function(err, req, res, user) { assert.isFalse(user); }, }, }, 'with a failed authentication containing info message using callback': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureInfoMessageStrategy()); var callback = function(err, user, info) { this.done(err, user, info); } var context = {}; var authenticate = passport.authenticate('failure', callback.bind(context)); process.nextTick(function () { self.callback(null, authenticate, context); }); }, 'when handling a request': { topic: function(authenticate, context) { var self = this; var req = new MockRequest(); var res = new MockResponse(); context.done = function(err, user, info) { self.callback(err, req, res, user, info); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res, user) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res, user) { assert.isUndefined(req.user); }, 'should pass user to callback as false' : function(err, req, res, user) { assert.isFalse(user); }, 'should pass info to callback' : function(err, req, res, user, info) { assert.isObject(info); assert.equal(info.message, 'Invalid password'); }, }, }, 'with a failed authentication containing info message using string message option': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureInfoMessageStrategy()); return passport.authenticate('failure', { failureMessage: 'Wrong credentials', failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.session = {}; res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set flash on request' : function(err, req, res) { assert.lengthOf(req.session.messages, 1); assert.equal(req.session.messages[0], 'Wrong credentials'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a failed authentication containing info message using string message option with existing messages': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureInfoMessageStrategy()); return passport.authenticate('failure', { failureMessage: 'Wrong credentials', failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.session = {}; req.session.messages = [ 'I exist!' ]; res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set flash on request' : function(err, req, res) { assert.lengthOf(req.session.messages, 2); assert.equal(req.session.messages[0], 'I exist!'); assert.equal(req.session.messages[1], 'Wrong credentials'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a failed authentication containing info message using boolean message option': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureInfoMessageStrategy()); return passport.authenticate('failure', { failureMessage: true, failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.session = {}; res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set flash on request' : function(err, req, res) { assert.lengthOf(req.session.messages, 1); assert.equal(req.session.messages[0], 'Invalid password'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a failed authentication containing info type and message using boolean message option': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureInfoTypeAndMessageStrategy()); return passport.authenticate('failure', { failureMessage: true, failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.session = {}; res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set flash on request' : function(err, req, res) { assert.lengthOf(req.session.messages, 1); assert.equal(req.session.messages[0], 'Invite required'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a failed authentication containing info message using boolean flash option': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureInfoMessageStrategy()); return passport.authenticate('failure', { failureFlash: true, failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'error'); assert.equal(req.message.msg, 'Invalid password'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a failed authentication containing info message using string flash option': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureInfoMessageStrategy()); return passport.authenticate('failure', { failureFlash: 'Wrong credentials', failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'error'); assert.equal(req.message.msg, 'Wrong credentials'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a failed authentication containing info message using flash option': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureInfoMessageStrategy()); return passport.authenticate('failure', { failureFlash: { type: 'notice', message: 'Try again' }, failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'notice'); assert.equal(req.message.msg, 'Try again'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a failed authentication containing info message using flash option with message only': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureInfoMessageStrategy()); return passport.authenticate('failure', { failureFlash: { message: 'Try again' }, failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'error'); assert.equal(req.message.msg, 'Try again'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a failed authentication containing info message using flash option with type only': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureInfoMessageStrategy()); return passport.authenticate('failure', { failureFlash: { type: 'info' }, failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'info'); assert.equal(req.message.msg, 'Invalid password'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a failed authentication containing info type and message using boolean flash option': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureInfoTypeAndMessageStrategy()); return passport.authenticate('failure', { failureFlash: true, failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'notice'); assert.equal(req.message.msg, 'Invite required'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a failed authentication containing info type and message using string flash option': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureInfoTypeAndMessageStrategy()); return passport.authenticate('failure', { failureFlash: 'Wrong credentials', failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'error'); assert.equal(req.message.msg, 'Wrong credentials'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a failed authentication containing info type and message using flash option': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureInfoTypeAndMessageStrategy()); return passport.authenticate('failure', { failureFlash: { type: 'info', message: 'Try again' }, failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'info'); assert.equal(req.message.msg, 'Try again'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a failed authentication containing info type and message using flash option with message only': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureInfoTypeAndMessageStrategy()); return passport.authenticate('failure', { failureFlash: { message: 'Try again' }, failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'error'); assert.equal(req.message.msg, 'Try again'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a failed authentication containing info type and message using flash option with type only': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureInfoTypeAndMessageStrategy()); return passport.authenticate('failure', { failureFlash: { type: 'info' }, failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'info'); assert.equal(req.message.msg, 'Invite required'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a failed authentication containing string message using boolean flash option': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureStringMessageStrategy()); return passport.authenticate('failure', { failureFlash: true, failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'error'); assert.equal(req.message.msg, 'Access denied'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a failed authentication containing string message using string flash option': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureStringMessageStrategy()); return passport.authenticate('failure', { failureFlash: 'Wrong credentials', failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'error'); assert.equal(req.message.msg, 'Wrong credentials'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a failed authentication containing string message using flash option': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureStringMessageStrategy()); return passport.authenticate('failure', { failureFlash: { type: 'notice', message: 'Try again' }, failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'notice'); assert.equal(req.message.msg, 'Try again'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a failed authentication containing string message using flash option with message only': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureStringMessageStrategy()); return passport.authenticate('failure', { failureFlash: { message: 'Try again' }, failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'error'); assert.equal(req.message.msg, 'Try again'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a failed authentication containing string message using flash option with type only': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureStringMessageStrategy()); return passport.authenticate('failure', { failureFlash: { type: 'info' }, failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'info'); assert.equal(req.message.msg, 'Access denied'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a failed authentication without info message and boolean flash option': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureStrategy()); return passport.authenticate('failure', { failureFlash: true, failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should not set flash on request' : function(err, req, res) { assert.isUndefined(req.message); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a failed authentication without info message and string flash option': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureStrategy()); return passport.authenticate('failure', { failureFlash: 'Wrong credentials', failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'error'); assert.equal(req.message.msg, 'Wrong credentials'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a failed authentication without info message and flash option': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureStrategy()); return passport.authenticate('failure', { failureFlash: { type: 'notice', message: 'Try again' }, failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'notice'); assert.equal(req.message.msg, 'Try again'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a failed authentication without info message and flash option with message only': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureStrategy()); return passport.authenticate('failure', { failureFlash: { message: 'Try again' }, failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set flash on request' : function(err, req, res) { assert.equal(req.message.type, 'error'); assert.equal(req.message.msg, 'Try again'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a failed authentication without info message and flash option with type only': { topic: function() { var self = this; var passport = new Passport(); passport.use('failure', new MockFailureStrategy()); return passport.authenticate('failure', { failureFlash: { type: 'info' }, failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should not set flash on request' : function(err, req, res) { assert.isUndefined(req.message); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a challenged authentication': { topic: function() { var self = this; var passport = new Passport(); passport.use('challenge', new MockChallengeStrategy()); return passport.authenticate('challenge'); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); res.end = function() { self.callback(null, req, res) } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set status code to unauthorized' : function(err, req, res) { assert.equal(res.statusCode, 401); }, 'should set WWW-Authenticate to challenge' : function(err, req, res) { assert.equal(res._headers['WWW-Authenticate'], 'Mock challenge'); }, }, }, 'with a challenged authentication and status code': { topic: function() { var self = this; var passport = new Passport(); passport.use('forbidden', new MockForbiddenStrategy()); return passport.authenticate('forbidden'); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); res.end = function() { self.callback(null, req, res) } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set status code to unauthorized' : function(err, req, res) { assert.equal(res.statusCode, 403); }, 'should set WWW-Authenticate to challenge' : function(err, req, res) { assert.equal(res._headers['WWW-Authenticate'], 'Mock challenge'); }, }, }, 'with a failed authentication due to bad request': { topic: function() { var self = this; var passport = new Passport(); passport.use('bad-request', new MockBadRequestStrategy()); return passport.authenticate('bad-request'); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); res.end = function() { self.callback(null, req, res) } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set status code to bad request' : function(err, req, res) { assert.equal(res.statusCode, 400); }, 'should not set WWW-Authenticate header' : function(err, req, res) { assert.isUndefined(res._headers['WWW-Authenticate']); }, }, }, 'with a multiple UI strategies with the first one succeeding': { topic: function() { var self = this; var passport = new Passport(); passport.use('local', new MockLocalStrategy()); passport.use('single-use-token', new MockSingleUseTokenStrategy()); return passport.authenticate(['local', 'single-use-token']); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); function next(err) { self.callback(err, req, res); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.username, 'bob-local'); }, }, }, 'with a multiple UI strategies with the second one succeeding': { topic: function() { var self = this; var passport = new Passport(); passport.use('local', new MockLocalStrategy({ fail: true })); passport.use('single-use-token', new MockSingleUseTokenStrategy()); return passport.authenticate(['local', 'single-use-token']); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); function next(err) { self.callback(err, req, res); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set user on request' : function(err, req, res) { assert.isObject(req.user); assert.equal(req.user.username, 'bob-sut'); }, }, }, 'with a multiple UI strategies with the both failing with flash message': { topic: function() { var self = this; var passport = new Passport(); passport.use('local', new MockLocalStrategy({ fail: true })); passport.use('single-use-token', new MockSingleUseTokenStrategy({ fail: true })); return passport.authenticate(['local', 'single-use-token'], { failureFlash: true, failureRedirect: 'http://www.example.com/login' }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); req.flash = function(type, msg) { this.message = { type: type, msg: msg } } var res = new MockResponse(); res.redirect = function(url) { this.location = url; self.callback(null, req, res); } function next(err) { self.callback(err, req, res); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set first flash on request' : function(err, req, res) { assert.equal(req.message.type, 'error'); assert.equal(req.message.msg, 'Bad username or password'); }, 'should redirect response' : function(err, req, res) { assert.equal(res.location, 'http://www.example.com/login'); }, }, }, 'with a multiple API strategies failing with default status': { topic: function() { var self = this; var passport = new Passport(); passport.use('basic', new MockBasicStrategy({ fail: true })); passport.use('digest', new MockDigestStrategy({ fail: true })); passport.use('nc', new MockNoChallengeStrategy({ fail: true })); return passport.authenticate(['basic', 'nc', 'digest'], { session: false }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); res.end = function() { self.callback(null, req, res) } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set status code to unauthorized' : function(err, req, res) { assert.equal(res.statusCode, 401); }, 'should set multiple WWW-Authenticate headers' : function(err, req, res) { assert.lengthOf(res._headers['WWW-Authenticate'], 2); assert.equal(res._headers['WWW-Authenticate'][0], 'Basic foo'); assert.equal(res._headers['WWW-Authenticate'][1], 'Digest foo'); }, }, }, 'with a multiple API strategies failing with different status': { topic: function() { var self = this; var passport = new Passport(); passport.use('basic', new MockBasicStrategy({ fail: true, statusCode: 400 })); passport.use('digest', new MockDigestStrategy({ fail: true, statusCode: 403 })); passport.use('nc', new MockNoChallengeStrategy({ fail: true, statusCode: 402 })); return passport.authenticate(['basic', 'nc', 'digest'], { session: false }); }, 'when handling a request': { topic: function(authenticate) { var self = this; var req = new MockRequest(); var res = new MockResponse(); res.end = function() { self.callback(null, req, res) } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res) { assert.isUndefined(req.user); }, 'should set status code to bad request' : function(err, req, res) { assert.equal(res.statusCode, 400); }, 'should set multiple WWW-Authenticate headers' : function(err, req, res) { assert.lengthOf(res._headers['WWW-Authenticate'], 2); assert.equal(res._headers['WWW-Authenticate'][0], 'Basic foo'); assert.equal(res._headers['WWW-Authenticate'][1], 'Digest foo'); }, }, }, 'with a single API strategy failing with challenge and status using custom callback': { topic: function() { var self = this; var passport = new Passport(); passport.use('basic', new MockBasicStrategy({ fail: true, statusCode: 400 })); var callback = function(err, user, challenge, status) { this.done(err, user, challenge, status); } var context = {}; var authenticate = passport.authenticate('basic', callback.bind(context)); process.nextTick(function () { self.callback(null, authenticate, context); }); }, 'when handling a request': { topic: function(authenticate, context) { var self = this; var req = new MockRequest(); var res = new MockResponse(); context.done = function(err, user, challenge, status) { self.callback(err, req, res, user, challenge, status); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res, user, challenge, status) { assert.isUndefined(req.user); }, 'should pass user to callback as false' : function(err, req, res, user, challenge, status) { assert.isFalse(user); }, 'should pass challenge to callback' : function(err, req, res, user, challenge, status) { assert.strictEqual(challenge, 'Basic foo'); }, 'should pass status to callback' : function(err, req, res, user, challenge, status) { assert.strictEqual(status, 400); }, }, }, 'with a multiple API strategies failing with default status using custom callback': { topic: function() { var self = this; var passport = new Passport(); passport.use('basic', new MockBasicStrategy({ fail: true })); passport.use('digest', new MockDigestStrategy({ fail: true })); passport.use('nc', new MockNoChallengeStrategy({ fail: true })); var callback = function(err, user, challenge, status) { this.done(err, user, challenge, status); } var context = {}; var authenticate = passport.authenticate(['basic', 'nc', 'digest'], callback.bind(context)); process.nextTick(function () { self.callback(null, authenticate, context); }); }, 'when handling a request': { topic: function(authenticate, context) { var self = this; var req = new MockRequest(); var res = new MockResponse(); context.done = function(err, user, challenge, status) { self.callback(err, req, res, user, challenge, status); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res, user, challenge, status) { assert.isUndefined(req.user); }, 'should pass user to callback as false' : function(err, req, res, user, challenge, status) { assert.isFalse(user); }, 'should pass challenges callback' : function(err, req, res, user, challenge, status) { assert.isArray(challenge); assert.lengthOf(challenge, 3); assert.equal(challenge[0], 'Basic foo'); assert.isUndefined(challenge[1]); assert.equal(challenge[2], 'Digest foo'); }, 'should pass statuses callback' : function(err, req, res, user, challenge, status) { assert.isArray(status); assert.lengthOf(status, 3); assert.isUndefined(status[0]); assert.isUndefined(status[1]); assert.isUndefined(status[2]); }, }, }, 'with a multiple API strategies failing with different status using custom callback': { topic: function() { var self = this; var passport = new Passport(); passport.use('basic', new MockBasicStrategy({ fail: true, statusCode: 400 })); passport.use('digest', new MockDigestStrategy({ fail: true, statusCode: 403 })); passport.use('nc', new MockNoChallengeStrategy({ fail: true, statusCode: 402 })); var callback = function(err, user, challenge, status) { this.done(err, user, challenge, status); } var context = {}; var authenticate = passport.authenticate(['basic', 'nc', 'digest'], callback.bind(context)); process.nextTick(function () { self.callback(null, authenticate, context); }); }, 'when handling a request': { topic: function(authenticate, context) { var self = this; var req = new MockRequest(); var res = new MockResponse(); context.done = function(err, user, challenge, status) { self.callback(err, req, res, user, challenge, status); } function next(err) { self.callback(new Error('should not be called')); } process.nextTick(function () { authenticate(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should not set user on request' : function(err, req, res, user, challenge, status) { assert.isUndefined(req.user); }, 'should pass user to callback as false' : function(err, req, res, user, challenge, status) { assert.isFalse(user); }, 'should pass challenges callback' : function(err, req, res, user, challenge, status) { assert.isArray(challenge); assert.lengthOf(challenge, 3); assert.equal(challenge[0], 'Basic foo'); assert.equal(challenge[1], 402); assert.equal(challenge[2], 'Digest foo'); }, 'should pass statuses callback' : function(err, req, res, user, challenge, status) { assert.isArray(status); assert.lengthOf(status, 3); assert.equal(status[0], 400); assert.isUndefined(status[1]); assert.equal(status[2], 403); }, }, }, }).export(module); passport-0.1.17/test/middleware/initialize-test.js000066400000000000000000000057611214404640600222350ustar00rootroot00000000000000var vows = require('vows'); var assert = require('assert'); var passport = require('passport'); var util = require('util'); var Passport = require('passport').Passport; vows.describe('initialize').addBatch({ 'middleware': { topic: function() { var self = this; var passport = new Passport(); passport.deserializeUser(function(obj, done) { done(null, { id: obj }); }); return passport.initialize(); }, 'when handling a request without a session': { topic: function(initialize) { var self = this; var req = {}; var res = {} function next(err) { self.callback(err, req, res); } process.nextTick(function () { initialize(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should set internal passport on the request' : function(err, req, res) { assert.isObject(req._passport); assert.instanceOf(req._passport.instance, Passport); assert.isObject(req._passport.session); }, }, 'when handling a request with a session': { topic: function(initialize) { var self = this; var req = {}; req.session = {}; var res = {} function next(err) { self.callback(err, req, res); } process.nextTick(function () { initialize(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should initialize a passport within the session' : function(err, req, res) { assert.isObject(req.session.passport); }, 'should set internal passport on the request' : function(err, req, res) { assert.isObject(req._passport); assert.instanceOf(req._passport.instance, Passport); assert.isObject(req._passport.session); }, }, 'when handling a request with a session containing passport data': { topic: function(initialize) { var self = this; var req = {}; req.session = {}; req.session.passport = {}; req.session.passport.user = '123456' var res = {} function next(err) { self.callback(err, req, res); } process.nextTick(function () { initialize(req, res, next) }); }, 'should not generate an error' : function(err, req, res) { assert.isNull(err); }, 'should maintain passport within the session' : function(err, req, res) { assert.isObject(req.session.passport); assert.isString(req.session.passport.user); }, 'should set internal passport on the request' : function(err, req, res) { assert.isObject(req._passport); assert.instanceOf(req._passport.instance, Passport); assert.isObject(req._passport.session); }, }, }, }).export(module); passport-0.1.17/test/strategies/000077500000000000000000000000001214404640600166055ustar00rootroot00000000000000passport-0.1.17/test/strategies/session-test.js000066400000000000000000000176141214404640600216140ustar00rootroot00000000000000var vows = require('vows'); var assert = require('assert'); var util = require('util'); var SessionStrategy = require('passport/strategies/session'); vows.describe('SessionStrategy').addBatch({ 'strategy': { topic: function() { return new SessionStrategy(); }, 'should be named session': function (strategy) { assert.equal(strategy.name, 'session'); }, }, 'strategy handling a request without a login session': { topic: function() { return new SessionStrategy(); }, 'after augmenting with actions': { topic: function(strategy) { var self = this; var req = {}; strategy.pass = function() { self.callback(null, req); } strategy.error = function(err) { self.callback(err, req); } req._passport = {}; req._passport.session = {}; process.nextTick(function () { strategy.authenticate(req); }); }, 'should not generate an error' : function(err, req) { assert.isNull(err); }, 'should not set a user on the request' : function(err, req) { assert.isUndefined(req.user); }, }, }, 'strategy handling a request with a login session': { topic: function() { return new SessionStrategy(); }, 'after augmenting with actions': { topic: function(strategy) { var self = this; var req = {}; strategy.pass = function() { self.callback(null, req); } strategy.error = function(err) { self.callback(err, req); } req._passport = {}; req._passport.instance = {}; req._passport.instance.deserializeUser = function(user, done) { done(null, { id: user }); } req._passport.session = {}; req._passport.session.user = '123456'; process.nextTick(function () { strategy.authenticate(req); }); }, 'should not generate an error' : function(err, req) { assert.isNull(err); }, 'should set a user on the request' : function(err, req) { assert.isObject(req.user); assert.equal(req.user.id, '123456'); }, 'should maintain the session' : function(err, req) { assert.isObject(req._passport.session); assert.equal(req._passport.session.user, '123456'); }, }, }, 'strategy handling a request with a login session using user ID 0': { topic: function() { return new SessionStrategy(); }, 'after augmenting with actions': { topic: function(strategy) { var self = this; var req = {}; strategy.pass = function() { self.callback(null, req); } strategy.error = function(err) { self.callback(err, req); } req._passport = {}; req._passport.instance = {}; req._passport.instance.deserializeUser = function(user, done) { done(null, { id: user }); } req._passport.session = {}; req._passport.session.user = 0; process.nextTick(function () { strategy.authenticate(req); }); }, 'should not generate an error' : function(err, req) { assert.isNull(err); }, 'should set a user on the request' : function(err, req) { assert.isObject(req.user); assert.equal(req.user.id, 0); }, 'should maintain the session' : function(err, req) { assert.isObject(req._passport.session); assert.equal(req._passport.session.user, 0); }, }, }, 'strategy handling a request with a login session that has been invalidated': { topic: function() { return new SessionStrategy(); }, 'after augmenting with actions': { topic: function(strategy) { var self = this; var req = {}; strategy.pass = function() { self.callback(null, req); } strategy.error = function(err) { self.callback(err, req); } req._passport = {}; req._passport.instance = {}; req._passport.instance.deserializeUser = function(user, done) { done(null, false); } req._passport.session = {}; req._passport.session.user = '123456'; process.nextTick(function () { strategy.authenticate(req); }); }, 'should not generate an error' : function(err, req) { assert.isNull(err); }, 'should not set a user on the request' : function(err, req) { assert.isUndefined(req.user); }, 'should remove user from the session' : function(err, req) { assert.isObject(req._passport.session); assert.isUndefined(req._passport.session.user); }, }, }, 'strategy handling a login session with a custom user property': { topic: function() { return new SessionStrategy(); }, 'after augmenting with actions': { topic: function(strategy) { var self = this; var req = {}; strategy.pass = function() { self.callback(null, req); } strategy.error = function(err) { self.callback(err, req); } req._passport = {}; req._passport.instance = {}; req._passport.instance._userProperty = 'currentUser'; req._passport.instance.deserializeUser = function(user, done) { done(null, { id: user }); } req._passport.session = {}; req._passport.session.user = '123456'; process.nextTick(function () { strategy.authenticate(req); }); }, 'should not generate an error' : function(err, req) { assert.isNull(err); }, 'should not set a property called "user" on the request': function(err, req) { assert.isUndefined(req.user); }, 'should set a a property called "currentUser" on the request' : function(err, req) { assert.isObject(req.currentUser); assert.equal(req.currentUser.id, '123456'); }, }, }, 'strategy handling a request with a login session but badly behaving user deserializer': { topic: function() { return new SessionStrategy(); }, 'after augmenting with actions': { topic: function(strategy) { var self = this; var req = {}; strategy.pass = function() { self.callback(null, req); } strategy.error = function(err) { self.callback(err, req); } req._passport = {}; req._passport.instance = {}; req._passport.instance.deserializeUser = function(user, done) { done(new Error('failed to deserialize')); } req._passport.session = {}; req._passport.session.user = '123456'; process.nextTick(function () { strategy.authenticate(req); }); }, 'should generate an error' : function(err, req) { assert.instanceOf(err, Error); }, 'should not set a user on the request' : function(err, req) { assert.isUndefined(req.user); }, }, }, 'strategy handling a request without an initialized passport': { topic: function() { return new SessionStrategy(); }, 'after augmenting with actions': { topic: function(strategy) { var self = this; var req = {}; strategy.error = function(err) { self.callback(err, req); } process.nextTick(function () { strategy.authenticate(req); }); }, 'should generate an error' : function(err, req) { assert.instanceOf(err, Error); }, 'should not set a user on the request' : function(err, req) { assert.isUndefined(req.user); }, }, }, }).export(module);