@passport-next/passport
Advanced tools
Comparing version 2.1.1 to 3.0.0
This changelog follows Semantic Versioning https://semver.org/ | ||
# 3.0.0 (2019-07-13) | ||
### Major | ||
* Major lint changes, there are no functional changes but due to the massive | ||
amount of code changes this is being marked as a major bump for caution sake | ||
this will hopefully be the last of the changes like this for a while. | ||
### Patch | ||
* Fixed premature redirect in logOut and improved test coverage #20 @rwky | ||
* Removed make-node and replaced with nyc and coveralls @rwky | ||
# 2.1.1 (2019-04-30) | ||
@@ -30,3 +44,3 @@ | ||
* Added eslint configuration, and fixed a pletora of lint errors @idurotola | ||
* This change should have been a patch (to 1.0.2) but because of the size of the | ||
This change should have been a patch (to 1.0.2) but because of the size of the | ||
number of lines changed it was made a major. | ||
@@ -33,0 +47,0 @@ |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
/** | ||
@@ -5,4 +7,2 @@ * Module dependencies. | ||
/* eslint-disable no-underscore-dangle, camelcase, no-proto, no-shadow */ | ||
const SessionStrategy = require('./strategies/session'); | ||
@@ -14,472 +14,480 @@ const SessionManager = require('./sessionmanager'); | ||
/** | ||
* `Authenticator` constructor. | ||
* The `Authenticator` constructor. | ||
* | ||
* @api public | ||
* @public | ||
*/ | ||
function Authenticator() { | ||
this._key = 'passport'; | ||
this._strategies = {}; | ||
this._serializers = []; | ||
this._deserializers = []; | ||
this._infoTransformers = []; | ||
this._framework = null; | ||
this._userProperty = 'user'; | ||
class Authenticator { | ||
constructor() { | ||
this._key = 'passport'; | ||
this._strategies = {}; | ||
this._serializers = []; | ||
this._deserializers = []; | ||
this._infoTransformers = []; | ||
this._framework = null; | ||
this._userProperty = 'user'; | ||
this.init(); | ||
} | ||
this.init(); | ||
} | ||
/** | ||
* Initialize authenticator. | ||
* | ||
* @api protected | ||
*/ | ||
Authenticator.prototype.init = function init() { | ||
this.framework(connect()); | ||
this.use(new SessionStrategy(this.deserializeUser.bind(this))); | ||
this._sm = new SessionManager({ key: this._key }, this.serializeUser.bind(this)); | ||
}; | ||
/** | ||
* 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 {Authenticator} for chaining | ||
* @api public | ||
*/ | ||
Authenticator.prototype.use = function use(name, strategy) { | ||
if (!strategy) { | ||
strategy = name; | ||
name = strategy.name; | ||
/** | ||
* Initialize authenticator. | ||
* @returns {void} | ||
* @protected | ||
*/ | ||
init() { | ||
this.framework(connect()); | ||
this.use(new SessionStrategy(this.deserializeUser.bind(this))); | ||
this._sm = new SessionManager({ key: this._key }, this.serializeUser.bind(this)); | ||
} | ||
if (!name) { throw new Error('Authentication strategies must have a name'); } | ||
this._strategies[name] = strategy; | ||
return this; | ||
}; | ||
/** | ||
* Utilize the given `strategy` with optional `name`, overridding the strategy's | ||
* default name. | ||
* | ||
* @example | ||
* | ||
* passport.use(new TwitterStrategy(...args)); | ||
* | ||
* passport.use('api', new http.BasicStrategy(...args)); | ||
* | ||
* @param {string|Strategy} name | ||
* @param {Strategy} strategy | ||
* @returns {Authenticator} for chaining | ||
* @public | ||
*/ | ||
use(name, strategy) { | ||
if (!strategy) { | ||
strategy = name; | ||
({ name } = strategy); | ||
} | ||
if (!name) { throw new Error('Authentication strategies must have a name'); } | ||
/** | ||
* 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 {Authenticator} for chaining | ||
* @api public | ||
*/ | ||
Authenticator.prototype.unuse = function unuse(name) { | ||
delete this._strategies[name]; | ||
return this; | ||
}; | ||
this._strategies[name] = strategy; | ||
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 {Authenticator} for chaining | ||
* @api public | ||
*/ | ||
Authenticator.prototype.framework = function framework(fw) { | ||
this._framework = fw; | ||
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. | ||
* | ||
* @example | ||
* | ||
* passport.unuse('legacy-api'); | ||
* | ||
* @param {string} name | ||
* @returns {Authenticator} for chaining | ||
* @public | ||
*/ | ||
unuse(name) { | ||
delete this._strategies[name]; | ||
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.use(passport.initialize()); | ||
* | ||
* app.use(passport.initialize({ userProperty: 'currentUser' })); | ||
* | ||
* @param {Object} options | ||
* @return {Function} middleware | ||
* @api public | ||
*/ | ||
Authenticator.prototype.initialize = function initialize(options) { | ||
options = options || {}; | ||
this._userProperty = options.userProperty || 'user'; | ||
/** | ||
* 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. | ||
* | ||
* @example | ||
* | ||
* passport.framework(require('hapi-passport')()); | ||
* | ||
* @param {object} fw | ||
* @returns {Authenticator} for chaining | ||
* @public | ||
*/ | ||
framework(fw) { | ||
this._framework = fw; | ||
return this; | ||
} | ||
return this._framework.initialize(this, options); | ||
}; | ||
/** | ||
* @typedef {Object} AuthenticatorInitializeOptions | ||
* @property {string} [userProperty="user"] Property to set on `req` upon login | ||
*/ | ||
/** | ||
* 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 | ||
*/ | ||
Authenticator.prototype.authenticate = function authenticate(strategy, options, callback) { | ||
return this._framework.authenticate(this, strategy, options, callback); | ||
}; | ||
/** | ||
* Passport's primary initialization middleware. | ||
* | ||
* This middleware must be in use by the Connect/Express application for | ||
* Passport to operate. | ||
* | ||
* @example | ||
* | ||
* app.use(passport.initialize()); | ||
* | ||
* app.use(passport.initialize({ userProperty: 'currentUser' })); | ||
* | ||
* @param {AuthenticatorInitializeOptions} options | ||
* @returns {GenericCallback} middleware | ||
* @public | ||
*/ | ||
initialize(options) { | ||
options = options || {}; | ||
this._userProperty = options.userProperty || 'user'; | ||
/** | ||
* 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 | ||
*/ | ||
Authenticator.prototype.authorize = function authorize(strategy, options, callback) { | ||
options = options || {}; | ||
options.assignProperty = 'account'; | ||
return this._framework.initialize(this, options); | ||
} | ||
const fn = this._framework.authorize || this._framework.authenticate; | ||
return fn(this, strategy, options, callback); | ||
}; | ||
/** | ||
* Middleware that will authenticate a request using the given `strategy` name, | ||
* with optional `options` and `callback`. | ||
* | ||
* @example | ||
* | ||
* passport.authenticate('local', { | ||
* successRedirect: '/', | ||
* failureRedirect: '/login' | ||
* })(req, res); | ||
* | ||
* passport.authenticate('local', (err, user) => { | ||
* if (err) { next(err); return; } | ||
* if (!user) { res.redirect('/login'); return; } | ||
* res.end('Authenticated!'); | ||
* })(req, res); | ||
* | ||
* passport.authenticate('basic', { session: false })(req, res); | ||
* | ||
* app.get('/auth/twitter', passport.authenticate('twitter'), (req, res) => { | ||
* // request will be redirected to Twitter | ||
* }); | ||
* app.get('/auth/twitter/callback', passport.authenticate('twitter'), (req, res) => { | ||
* res.json(req.user); | ||
* }); | ||
* | ||
* @param {string} strategy | ||
* @param {object} options | ||
* @param {GenericCallback} callback | ||
* @returns {GenericCallback} middleware | ||
* @public | ||
*/ | ||
authenticate(strategy, options, callback) { | ||
return this._framework.authenticate(this, strategy, options, callback); | ||
} | ||
/** | ||
* 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.use(connect.cookieParser()); | ||
* app.use(connect.session({ secret: 'keyboard cat' })); | ||
* app.use(passport.initialize()); | ||
* app.use(passport.session()); | ||
* | ||
* @param {Object} options | ||
* @return {Function} middleware | ||
* @api public | ||
*/ | ||
Authenticator.prototype.session = function session(options) { | ||
return this.authenticate('session', options); | ||
}; | ||
/** | ||
* 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. | ||
* | ||
* @example | ||
* | ||
* passport.authorize('twitter-authz', { failureRedirect: '/account' }); | ||
* | ||
* @param {string} strategy | ||
* @param {object} options | ||
* @param {GenericCallback} callback | ||
* @returns {GenericCallback} middleware | ||
* @public | ||
*/ | ||
authorize(strategy, options, callback) { | ||
options = options || {}; | ||
options.assignProperty = 'account'; | ||
/** | ||
* Sets a custom SessionManager | ||
* | ||
* Examples: | ||
* | ||
* passport.sessionManager = new CustomSessionManager(); | ||
* | ||
* @api public | ||
*/ | ||
const fn = this._framework.authorize || this._framework.authenticate; | ||
return fn(this, strategy, options, callback); | ||
} | ||
Authenticator.prototype.sessionManager = function sessionManager(mgr) { | ||
this._sm = mgr; | ||
return 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. | ||
* | ||
* @example | ||
* | ||
* app.use(connect.cookieParser()); | ||
* app.use(connect.session({ secret: 'keyboard cat' })); | ||
* app.use(passport.initialize()); | ||
* app.use(passport.session()); | ||
* | ||
* @param {object} options | ||
* @returns {GenericCallback} middleware | ||
* @public | ||
*/ | ||
session(options) { | ||
return this.authenticate('session', options); | ||
} | ||
/** | ||
* Registers a function used to serialize user objects into the session. | ||
* | ||
* Examples: | ||
* | ||
* passport.serializeUser(function(user, done) { | ||
* done(null, user.id); | ||
* }); | ||
* | ||
* @api public | ||
*/ | ||
/** | ||
* Sets a custom SessionManager | ||
* | ||
* @example | ||
* | ||
* passport.sessionManager = new CustomSessionManager(); | ||
* | ||
* @public | ||
*/ | ||
// eslint-disable-next-line consistent-return | ||
Authenticator.prototype.serializeUser = function serializeUser(fn, req, done) { | ||
if (typeof fn === 'function') { | ||
return this._serializers.push(fn); | ||
sessionManager(mgr) { | ||
this._sm = mgr; | ||
return this; | ||
} | ||
// private implementation that traverses the chain of serializers, attempting | ||
// to serialize a user | ||
const user = fn; | ||
/** | ||
* Registers a function used to serialize user objects into the session. | ||
* | ||
* @example | ||
* | ||
* passport.serializeUser(function(user, done) { | ||
* done(null, user.id); | ||
* }); | ||
* | ||
* @public | ||
*/ | ||
// For backwards compatibility | ||
if (typeof req === 'function') { | ||
done = req; | ||
req = undefined; | ||
} | ||
const stack = this._serializers; | ||
// eslint-disable-next-line consistent-return | ||
(function pass(i, err, obj) { | ||
// serializers use 'pass' as an error to skip processing | ||
if (err === 'pass') { | ||
err = undefined; | ||
serializeUser(fn, req, done) { | ||
if (typeof fn === 'function') { | ||
return this._serializers.push(fn); | ||
} | ||
// an error or serialized object was obtained, done | ||
if (err || obj || obj === 0) { return done(err, obj); } | ||
const layer = stack[i]; | ||
if (!layer) { | ||
return done(new Error('Failed to serialize user into session')); | ||
} | ||
// private implementation that traverses the chain of serializers, attempting | ||
// to serialize a user | ||
const user = fn; | ||
function serialized(e, o) { | ||
pass(i + 1, e, o); | ||
// For backwards compatibility | ||
if (typeof req === 'function') { | ||
done = req; | ||
req = undefined; | ||
} | ||
try { | ||
const arity = layer.length; | ||
if (arity === 3) { | ||
layer(req, user, serialized); | ||
} else { | ||
layer(user, serialized); | ||
const stack = this._serializers; | ||
// eslint-disable-next-line consistent-return | ||
(function pass(i, err, obj) { | ||
// serializers use 'pass' as an error to skip processing | ||
if (err === 'pass') { | ||
err = undefined; | ||
} | ||
} catch (e) { | ||
return done(e); | ||
} | ||
}(0)); | ||
}; | ||
// an error or serialized object was obtained, done | ||
if (err || obj || obj === 0) { return done(err, obj); } | ||
/** | ||
* 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 | ||
*/ | ||
const layer = stack[i]; | ||
if (!layer) { | ||
return done(new Error('Failed to serialize user into session')); | ||
} | ||
// eslint-disable-next-line consistent-return | ||
Authenticator.prototype.deserializeUser = function deserializeUser(fn, req, done) { | ||
if (typeof fn === 'function') { | ||
return this._deserializers.push(fn); | ||
} | ||
// private implementation that traverses the chain of deserializers, | ||
// attempting to deserialize a user | ||
const obj = fn; | ||
// eslint-disable-next-line jsdoc/require-jsdoc | ||
function serialized(e, o) { | ||
pass(i + 1, e, o); | ||
} | ||
// For backwards compatibility | ||
if (typeof req === 'function') { | ||
done = req; | ||
req = undefined; | ||
try { | ||
const arity = layer.length; | ||
if (arity === 3) { | ||
layer(req, user, serialized); | ||
} else { | ||
layer(user, serialized); | ||
} | ||
} catch (e) { | ||
return done(e); | ||
} | ||
}(0)); | ||
} | ||
const stack = this._deserializers; | ||
/** | ||
* Registers a function used to deserialize user objects out of the session. | ||
* | ||
* @example | ||
* | ||
* passport.deserializeUser(function(id, done) { | ||
* User.findById(id, function (err, user) { | ||
* done(err, user); | ||
* }); | ||
* }); | ||
* | ||
* @public | ||
*/ | ||
// eslint-disable-next-line consistent-return | ||
(function pass(i, err, user) { | ||
// deserializers use 'pass' as an error to skip processing | ||
if (err === 'pass') { | ||
err = undefined; | ||
deserializeUser(fn, req, done) { | ||
if (typeof fn === 'function') { | ||
return this._deserializers.push(fn); | ||
} | ||
// 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); } | ||
const layer = stack[i]; | ||
if (!layer) { | ||
return done(new Error('Failed to deserialize user out of session')); | ||
} | ||
// private implementation that traverses the chain of deserializers, | ||
// attempting to deserialize a user | ||
const obj = fn; | ||
function deserialized(e, u) { | ||
pass(i + 1, e, u); | ||
// For backwards compatibility | ||
if (typeof req === 'function') { | ||
done = req; | ||
req = undefined; | ||
} | ||
try { | ||
const arity = layer.length; | ||
if (arity === 3) { | ||
layer(req, obj, deserialized); | ||
} else { | ||
layer(obj, deserialized); | ||
const stack = this._deserializers; | ||
// eslint-disable-next-line consistent-return | ||
(function pass(i, err, user) { | ||
// deserializers use 'pass' as an error to skip processing | ||
if (err === 'pass') { | ||
err = undefined; | ||
} | ||
} catch (e) { | ||
return done(e); | ||
} | ||
}(0)); | ||
}; | ||
// 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); } | ||
/** | ||
* 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 | ||
*/ | ||
const layer = stack[i]; | ||
if (!layer) { | ||
return done(new Error('Failed to deserialize user out of session')); | ||
} | ||
// eslint-disable-next-line consistent-return | ||
Authenticator.prototype.transformAuthInfo = function transformAuthInfo(fn, req, done) { | ||
if (typeof fn === 'function') { | ||
return this._infoTransformers.push(fn); | ||
} | ||
// private implementation that traverses the chain of transformers, | ||
// attempting to transform auth info | ||
const info = fn; | ||
// eslint-disable-next-line jsdoc/require-jsdoc | ||
function deserialized(e, u) { | ||
pass(i + 1, e, u); | ||
} | ||
// For backwards compatibility | ||
if (typeof req === 'function') { | ||
done = req; | ||
req = undefined; | ||
try { | ||
const arity = layer.length; | ||
if (arity === 3) { | ||
layer(req, obj, deserialized); | ||
} else { | ||
layer(obj, deserialized); | ||
} | ||
} catch (e) { | ||
return done(e); | ||
} | ||
}(0)); | ||
} | ||
const stack = this._infoTransformers; | ||
/** | ||
* 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. | ||
* | ||
* @example | ||
* | ||
* passport.transformAuthInfo(function(info, done) { | ||
* Client.findById(info.clientID, function (err, client) { | ||
* info.client = client; | ||
* done(err, info); | ||
* }); | ||
* }); | ||
* | ||
* @public | ||
*/ | ||
// eslint-disable-next-line consistent-return | ||
(function pass(i, err, tinfo) { | ||
// transformers use 'pass' as an error to skip processing | ||
if (err === 'pass') { | ||
err = undefined; | ||
transformAuthInfo(fn, req, done) { | ||
if (typeof fn === 'function') { | ||
return this._infoTransformers.push(fn); | ||
} | ||
// an error or transformed info was obtained, done | ||
if (err || tinfo) { return done(err, tinfo); } | ||
const 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); | ||
// private implementation that traverses the chain of transformers, | ||
// attempting to transform auth info | ||
const info = fn; | ||
// For backwards compatibility | ||
if (typeof req === 'function') { | ||
done = req; | ||
req = undefined; | ||
} | ||
const stack = this._infoTransformers; | ||
// eslint-disable-next-line consistent-return | ||
(function pass(i, err, tinfo) { | ||
// transformers use 'pass' as an error to skip processing | ||
if (err === 'pass') { | ||
err = undefined; | ||
} | ||
// an error or transformed info was obtained, done | ||
if (err || tinfo) { return done(err, tinfo); } | ||
function transformed(e, t) { | ||
pass(i + 1, e, t); | ||
} | ||
const 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 { | ||
const arity = layer.length; | ||
if (arity === 1) { | ||
// sync | ||
const t = layer(info); | ||
transformed(null, t); | ||
} else if (arity === 3) { | ||
layer(req, info, transformed); | ||
} else { | ||
layer(info, transformed); | ||
// eslint-disable-next-line jsdoc/require-jsdoc | ||
function transformed(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 | ||
*/ | ||
Authenticator.prototype._strategy = function _strategy(name) { | ||
return this._strategies[name]; | ||
}; | ||
try { | ||
const arity = layer.length; | ||
if (arity === 1) { | ||
// sync | ||
const t = layer(info); | ||
transformed(null, t); | ||
} else if (arity === 3) { | ||
layer(req, info, transformed); | ||
} else { | ||
layer(info, transformed); | ||
} | ||
} catch (e) { | ||
return done(e); | ||
} | ||
}(0)); | ||
} | ||
/** | ||
* Return strategy with given `name`. | ||
* | ||
* @param {string} name | ||
* @returns {Strategy} | ||
* @private | ||
*/ | ||
_strategy(name) { | ||
return this._strategies[name]; | ||
} | ||
} | ||
@@ -486,0 +494,0 @@ /** |
@@ -0,23 +1,18 @@ | ||
'use strict'; | ||
/** | ||
* `AuthenticationError` error. | ||
* The `AuthenticationError` error. | ||
* | ||
* @constructor | ||
* @api private | ||
* @private | ||
*/ | ||
/* eslint-disable no-proto, no-proto, no-caller, no-restricted-properties */ | ||
function AuthenticationError(message, status) { | ||
Error.call(this); | ||
Error.captureStackTrace(this, arguments.callee); | ||
this.name = 'AuthenticationError'; | ||
this.message = message; | ||
this.status = status || 401; | ||
class AuthenticationError extends Error { | ||
constructor(message, status) { | ||
super(message); | ||
Error.captureStackTrace(this, AuthenticationError); | ||
this.name = 'AuthenticationError'; | ||
this.status = status || 401; | ||
} | ||
} | ||
// Inherit from `Error`. | ||
AuthenticationError.prototype.__proto__ = Error.prototype; | ||
// Expose constructor. | ||
module.exports = AuthenticationError; |
@@ -0,5 +1,6 @@ | ||
'use strict'; | ||
/** | ||
* Module dependencies. | ||
*/ | ||
/* eslint-disable camelcase, no-proto, no-shadow */ | ||
@@ -16,3 +17,3 @@ const initialize = require('../middleware/initialize'); | ||
* @return {Object} | ||
* @api protected | ||
* @protected | ||
*/ | ||
@@ -24,4 +25,4 @@ | ||
initialize, | ||
authenticate, | ||
authenticate | ||
}; | ||
}; |
/** | ||
* Module dependencies. | ||
*/ | ||
'use strict'; | ||
// var http = require('http') | ||
// const http = require('http') | ||
// , req = http.IncomingMessage.prototype; | ||
/* eslint-disable no-multi-assign, camelcase, no-proto, no-shadow */ | ||
/* eslint-disable no-multi-assign */ | ||
const req = exports = module.exports = {}; | ||
/* eslint-enable no-multi-assign */ | ||
/** | ||
* @typedef {Object} LogInOptions | ||
* @property {boolean} [session] Save login state in session, defaults to _true_ | ||
*/ | ||
/** | ||
* Initiate a login session for `user`. | ||
* | ||
* Options: | ||
* - `session` Save login state in session, defaults to _true_ | ||
* | ||
* Examples: | ||
* @example | ||
* | ||
* req.logIn(user, { session: false }); | ||
* | ||
* req.logIn(user, function(err) { | ||
* req.logIn(user, (err) => { | ||
* if (err) { throw err; } | ||
@@ -28,5 +32,6 @@ * // session saved | ||
* @param {User} user | ||
* @param {Object} options | ||
* @param {Function} done | ||
* @api public | ||
* @param {LogInOptions} options | ||
* @param {GenericCallback} done | ||
* @returns {void} | ||
* @public | ||
*/ | ||
@@ -49,8 +54,7 @@ req.logIn = function logIn(user, options, done) { | ||
if (!this._passport) { throw new Error('passport.initialize() middleware not in use'); } | ||
if (typeof done !== 'function') { throw new Error('req#login requires a callback function'); } | ||
if (typeof done !== 'function') { throw new TypeError('req#login requires a callback function'); } | ||
const self = this; | ||
// eslint-disable-next-line consistent-return | ||
this._passport.instance._sm.logIn(this, user, (err) => { | ||
if (err) { self[property] = null; return done(err); } | ||
if (err) { this[property] = null; return done(err); } | ||
done(); | ||
@@ -68,6 +72,7 @@ }); | ||
* Terminate an existing login session. | ||
* | ||
* @api public | ||
* @param {GenericCallback} done | ||
* @returns {void} | ||
* @public | ||
*/ | ||
req.logOut = function logOut() { | ||
req.logOut = function logOut(done) { | ||
let property = 'user'; | ||
@@ -80,3 +85,3 @@ if (this._passport && this._passport.instance) { | ||
if (this._passport) { | ||
this._passport.instance._sm.logOut(this); | ||
this._passport.instance._sm.logOut(this, done); | ||
} | ||
@@ -90,4 +95,4 @@ }; | ||
* | ||
* @return {Boolean} | ||
* @api public | ||
* @returns {boolean} | ||
* @public | ||
*/ | ||
@@ -100,3 +105,3 @@ req.isAuthenticated = function isAuthenticated() { | ||
return !!(this[property]); | ||
return Boolean(this[property]); | ||
}; | ||
@@ -107,4 +112,4 @@ | ||
* | ||
* @return {Boolean} | ||
* @api public | ||
* @returns {boolean} | ||
* @public | ||
*/ | ||
@@ -111,0 +116,0 @@ req.isUnauthenticated = function isUnauthenticated() { |
@@ -6,2 +6,3 @@ /** | ||
/* eslint-disable no-multi-assign */ | ||
'use strict'; | ||
@@ -15,3 +16,3 @@ const Passport = require('./authenticator'); | ||
* | ||
* @api public | ||
* @public | ||
*/ | ||
@@ -18,0 +19,0 @@ exports = module.exports = new Passport(); |
@@ -0,1 +1,4 @@ | ||
/* eslint-disable no-shadow */ | ||
'use strict'; | ||
/** | ||
@@ -5,4 +8,2 @@ * Module dependencies. | ||
/* eslint-disable camelcase, no-proto, no-shadow */ | ||
const http = require('http'); | ||
@@ -58,3 +59,3 @@ const AuthenticationError = require('../errors/authenticationerror'); | ||
* | ||
* Examples: | ||
* @example | ||
* | ||
@@ -67,7 +68,8 @@ * passport.authenticate('local', { successRedirect: '/', failureRedirect: '/login' }); | ||
* | ||
* @param {String|Array} name | ||
* @param {Object} options | ||
* @param {Function} callback | ||
* @return {Function} | ||
* @api public | ||
* @param {Authenticator} passport | ||
* @param {string|Array} name | ||
* @param {object} options | ||
* @param {GenericCallback} callback | ||
* @returns {GenericCallback} | ||
* @public | ||
*/ | ||
@@ -102,2 +104,3 @@ module.exports = function authenticate(passport, name, options, callback) { | ||
// eslint-disable-next-line jsdoc/require-jsdoc | ||
function redirect(url) { | ||
@@ -110,3 +113,3 @@ if (req.session && req.session.save && typeof req.session.save === 'function') { | ||
// eslint-disable-next-line consistent-return | ||
// eslint-disable-next-line consistent-return, jsdoc/require-jsdoc | ||
function allFailed() { | ||
@@ -124,5 +127,4 @@ if (callback) { | ||
// message, the first failure will be displayed. | ||
let failure = failures[0] || {}; | ||
let challenge = failure.challenge || {}; | ||
let msg; | ||
const failure = failures[0] || {}; | ||
const challenge = failure.challenge || {}; | ||
@@ -134,6 +136,8 @@ if (options.failureFlash) { | ||
} | ||
flash.type = flash.type || 'error'; | ||
if (typeof flash !== 'boolean') { | ||
flash.type = flash.type || 'error'; | ||
} | ||
const type = flash.type || challenge.type || 'error'; | ||
msg = flash.message || challenge.message || challenge; | ||
const msg = flash.message || challenge.message || challenge; | ||
if (typeof msg === 'string') { | ||
@@ -144,3 +148,3 @@ req.flash(type, msg); | ||
if (options.failureMessage) { | ||
msg = options.failureMessage; | ||
let msg = options.failureMessage; | ||
if (typeof msg === 'boolean') { | ||
@@ -165,9 +169,3 @@ msg = challenge.message || challenge; | ||
let rstatus; | ||
let status; | ||
// eslint-disable-next-line no-plusplus | ||
for (let j = 0, len = failures.length; j < len; j++) { | ||
failure = failures[j]; | ||
challenge = failure.challenge; | ||
status = failure.status; | ||
failures.forEach(({ challenge, status }) => { | ||
rstatus = rstatus || status; | ||
@@ -177,3 +175,3 @@ if (typeof challenge === 'string') { | ||
} | ||
} | ||
}); | ||
@@ -224,3 +222,3 @@ res.statusCode = rstatus || 401; | ||
* @param {Object} info | ||
* @api public | ||
* @public | ||
*/ | ||
@@ -242,3 +240,5 @@ | ||
} | ||
flash.type = flash.type || 'success'; | ||
if (typeof flash !== 'boolean') { | ||
flash.type = flash.type || 'success'; | ||
} | ||
@@ -270,3 +270,3 @@ const type = flash.type || info.type || 'success'; | ||
// eslint-disable-next-line consistent-return | ||
// eslint-disable-next-line consistent-return, jsdoc/require-jsdoc | ||
function complete() { | ||
@@ -306,5 +306,6 @@ if (options.successReturnToOrRedirect) { | ||
* | ||
* @param {String} challenge | ||
* @param {Number} status | ||
* @api public | ||
* @param {string} challenge | ||
* @param {number} status | ||
* @returns {void} | ||
* @public | ||
*/ | ||
@@ -329,5 +330,6 @@ strategy.fail = function fail(challenge, status) { | ||
* | ||
* @param {String} url | ||
* @param {Number} status | ||
* @api public | ||
* @param {string} url | ||
* @param {number} status | ||
* @returns {void} | ||
* @public | ||
*/ | ||
@@ -359,3 +361,4 @@ strategy.redirect = function redirect(url, status) { | ||
* | ||
* @api public | ||
* @returns {void} | ||
* @public | ||
*/ | ||
@@ -374,3 +377,3 @@ strategy.pass = function pass() { | ||
* @param {Error} err | ||
* @api public | ||
* @public | ||
*/ | ||
@@ -377,0 +380,0 @@ |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
/** | ||
@@ -22,3 +24,3 @@ * Passport initialization. | ||
* | ||
* Examples: | ||
* @example | ||
* | ||
@@ -41,3 +43,3 @@ * app.use(connect.cookieParser()); | ||
* @return {Function} | ||
* @api public | ||
* @public | ||
*/ | ||
@@ -47,4 +49,4 @@ | ||
/* eslint-disable no-proto, no-shadow */ | ||
module.exports = function initialize(passport) { | ||
/* eslint-disable-next-line no-shadow */ | ||
return function initialize(req, res, next) { | ||
@@ -51,0 +53,0 @@ req._passport = {}; |
@@ -1,42 +0,43 @@ | ||
/* eslint-disable camelcase, no-proto, no-shadow */ | ||
'use strict'; | ||
function SessionManager(options, serializeUser) { | ||
if (typeof options === 'function') { | ||
serializeUser = options; | ||
options = undefined; | ||
class SessionManager { | ||
constructor(options, serializeUser) { | ||
if (typeof options === 'function') { | ||
serializeUser = options; | ||
options = undefined; | ||
} | ||
options = options || {}; | ||
this._key = options.key || 'passport'; | ||
this._serializeUser = serializeUser; | ||
} | ||
options = options || {}; | ||
this._key = options.key || 'passport'; | ||
this._serializeUser = serializeUser; | ||
} | ||
logIn(req, user, cb) { | ||
// eslint-disable-next-line consistent-return | ||
this._serializeUser(user, req, (err, obj) => { | ||
if (err) { | ||
return cb(err); | ||
} | ||
if (!req._passport.session) { | ||
req._passport.session = {}; | ||
} | ||
req._passport.session.user = obj; | ||
if (!req.session) { | ||
req.session = {}; | ||
} | ||
req.session[this._key] = req._passport.session; | ||
cb(); | ||
}); | ||
} | ||
SessionManager.prototype.logIn = function logIn(req, user, cb) { | ||
const self = this; | ||
// eslint-disable-next-line consistent-return | ||
this._serializeUser(user, req, (err, obj) => { | ||
if (err) { | ||
return cb(err); | ||
// eslint-disable-next-line class-methods-use-this | ||
logOut(req, cb) { | ||
if (req._passport && req._passport.session) { | ||
delete req._passport.session.user; | ||
} | ||
if (!req._passport.session) { | ||
req._passport.session = {}; | ||
} | ||
req._passport.session.user = obj; | ||
if (!req.session) { | ||
req.session = {}; | ||
} | ||
req.session[self._key] = req._passport.session; | ||
cb(); | ||
}); | ||
}; | ||
SessionManager.prototype.logOut = function logOut(req, cb) { | ||
if (req._passport && req._passport.session) { | ||
delete req._passport.session.user; | ||
// eslint-disable-next-line no-unused-expressions | ||
cb && cb(); | ||
} | ||
// eslint-disable-next-line no-unused-expressions | ||
cb && cb(); | ||
}; | ||
} | ||
module.exports = SessionManager; |
@@ -0,1 +1,2 @@ | ||
'use strict'; | ||
/** | ||
@@ -5,75 +6,67 @@ * Module dependencies. | ||
/* eslint-disable camelcase, no-proto, no-shadow */ | ||
const util = require('util'); | ||
const Strategy = require('@passport-next/passport-strategy'); | ||
/** | ||
* `SessionStrategy` constructor. | ||
* The `SessionStrategy` constructor. | ||
* | ||
* @api public | ||
* @public | ||
*/ | ||
function SessionStrategy(options, deserializeUser) { | ||
if (typeof options === 'function') { | ||
deserializeUser = options; | ||
options = undefined; | ||
class SessionStrategy extends Strategy { | ||
constructor(options, deserializeUser) { | ||
if (typeof options === 'function') { | ||
deserializeUser = options; | ||
options = undefined; | ||
} | ||
options = options || {}; | ||
super(); | ||
this.name = 'session'; | ||
this._deserializeUser = deserializeUser; | ||
} | ||
options = options || {}; | ||
Strategy.call(this); | ||
this.name = 'session'; | ||
this._deserializeUser = deserializeUser; | ||
} | ||
/** | ||
* 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 | ||
* @protected | ||
*/ | ||
/** | ||
* Inherit from `Strategy`. | ||
*/ | ||
util.inherits(SessionStrategy, Strategy); | ||
// eslint-disable-next-line consistent-return, no-unused-vars | ||
authenticate(req, options) { | ||
if (!req._passport) { return this.error(new Error('passport.initialize() middleware not in use')); } | ||
options = options || {}; | ||
/** | ||
* 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 | ||
*/ | ||
let su; | ||
// eslint-disable-next-line consistent-return, no-unused-vars | ||
SessionStrategy.prototype.authenticate = function authenticate(req, options) { | ||
if (!req._passport) { return this.error(new Error('passport.initialize() middleware not in use')); } | ||
options = options || {}; | ||
if (req._passport.session) { | ||
su = req._passport.session.user; | ||
} | ||
const self = this; | ||
let su; | ||
if (req._passport.session) { | ||
su = req._passport.session.user; | ||
if (su || su === 0) { | ||
// eslint-disable-next-line consistent-return | ||
this._deserializeUser(su, req, (err, user) => { | ||
if (err) { return this.error(err); } | ||
if (!user) { | ||
delete req._passport.session.user; | ||
} else { | ||
// TODO: Remove instance access | ||
const property = req._passport.instance._userProperty || 'user'; | ||
req[property] = user; | ||
} | ||
this.pass(); | ||
}); | ||
} else { | ||
this.pass(); | ||
} | ||
} | ||
} | ||
if (su || su === 0) { | ||
// eslint-disable-next-line consistent-return | ||
this._deserializeUser(su, req, (err, user) => { | ||
if (err) { return self.error(err); } | ||
if (!user) { | ||
delete req._passport.session.user; | ||
} else { | ||
// TODO: Remove instance access | ||
const property = req._passport.instance._userProperty || 'user'; | ||
req[property] = user; | ||
} | ||
self.pass(); | ||
}); | ||
} else { | ||
self.pass(); | ||
} | ||
}; | ||
/** | ||
@@ -80,0 +73,0 @@ * Expose `SessionStrategy`. |
115
package.json
{ | ||
"name": "@passport-next/passport", | ||
"version": "2.1.1", | ||
"description": "Simple, unobtrusive authentication for Node.js.", | ||
"keywords": [ | ||
"express", | ||
"connect", | ||
"auth", | ||
"authn", | ||
"authentication" | ||
], | ||
"author": { | ||
"name": "Rowan Wookey", | ||
"email": "admin@rwky.net" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/passport-next/passport.git" | ||
}, | ||
"bugs": { | ||
"url": "http://github.com/passport-next/passport/issues" | ||
}, | ||
"license": "MIT", | ||
"licenses": [ | ||
{ | ||
"type": "MIT", | ||
"url": "http://opensource.org/licenses/MIT" | ||
"name": "@passport-next/passport", | ||
"version": "3.0.0", | ||
"description": "Simple, unobtrusive authentication for Node.js.", | ||
"author": { | ||
"name": "Passport Next Developers", | ||
"url": "https://github.com/orgs/passport-next/people" | ||
}, | ||
"homepage": "https://github.com/passport-next/passport", | ||
"contributors": [ | ||
"Brett Zamir" | ||
], | ||
"bugs": { | ||
"url": "https://github.com/passport-next/passport/issues" | ||
}, | ||
"dependencies": { | ||
"@passport-next/passport-strategy": "1.x.x" | ||
}, | ||
"devDependencies": { | ||
"@mysticatea/eslint-plugin": "^10.0.3", | ||
"@passport-next/chai-passport-strategy": "1.x.x", | ||
"@passport-next/eslint-config-passport-next": "1.x.x", | ||
"chai": "4.x.x", | ||
"chai-connect-middleware": "0.x.x", | ||
"coveralls": "^3.0.5", | ||
"eslint": "^5.16.0", | ||
"eslint-config-standard": "^12.0.0", | ||
"eslint-plugin-compat": "^3.1.1", | ||
"eslint-plugin-eslint-comments": "^3.1.1", | ||
"eslint-plugin-import": "^2.17.3", | ||
"eslint-plugin-jsdoc": "^8.0.0", | ||
"eslint-plugin-markdown": "^1.0.0", | ||
"eslint-plugin-no-use-extend-native": "^0.4.0", | ||
"eslint-plugin-node": "^9.1.0", | ||
"eslint-plugin-promise": "^4.1.1", | ||
"eslint-plugin-standard": "^4.0.0", | ||
"eslint-plugin-unicorn": "^9.1.0", | ||
"make-node": "^0.4.6", | ||
"mocha": "6.x.x", | ||
"nunjucks": "^3.2.0", | ||
"nyc": "^14.1.1" | ||
}, | ||
"engines": { | ||
"node": ">=8.0.0" | ||
}, | ||
"keywords": [ | ||
"express", | ||
"connect", | ||
"auth", | ||
"authn", | ||
"authentication" | ||
], | ||
"license": "MIT", | ||
"main": "./lib", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/passport-next/passport" | ||
}, | ||
"scripts": { | ||
"templates": "node ./templates/gen.js", | ||
"init-new-project": "node ./templates/gen --init", | ||
"lint": "eslint --max-warnings 0 --ext js,md .", | ||
"lintfix": "eslint --ext js,md . --fix", | ||
"test": "mocha --reporter spec --require test/bootstrap/node test/*.test.js test/**/*.test.js", | ||
"coverage": "nyc --report-dir=var/coverage --reporter=lcov npm test", | ||
"coveralls": "nyc report --report-dir=var/coverage --reporter=text-lcov | coveralls" | ||
} | ||
], | ||
"main": "./lib", | ||
"dependencies": { | ||
"@passport-next/passport-strategy": "1.x.x" | ||
}, | ||
"devDependencies": { | ||
"@passport-next/chai-passport-strategy": "1.x.x", | ||
"chai": "4.x.x", | ||
"chai-connect-middleware": "0.x.x", | ||
"eslint": "^5.16.0", | ||
"eslint-config-airbnb-base": "13.x.x", | ||
"eslint-plugin-import": "^2.17.2", | ||
"make-node": "^0.4.6", | ||
"mocha": "6.x.x" | ||
}, | ||
"engines": { | ||
"node": ">=6.0.0" | ||
}, | ||
"scripts": { | ||
"spec": "node_modules/.bin/mocha --reporter spec --require test/bootstrap/node test/*.test.js test/**/*.test.js", | ||
"lint": "eslint --ext .js . --max-warnings 0", | ||
"lintfix": "eslint --ext .js . --fix", | ||
"test": "npm run lint && npm run spec" | ||
} | ||
} |
187
README.md
@@ -1,3 +0,13 @@ | ||
# Passport-Next/Passport | ||
# Passport-Next/Passport | ||
Status: | ||
[![NPM version](https://img.shields.io/npm/v/@passport-next/passport.svg)](https://www.npmjs.com/package/@passport-next/passport) | ||
[![Build Status](https://travis-ci.org/passport-next/passport.svg?branch=master)](https://travis-ci.org/passport-next/passport) | ||
[![Coverage Status](https://coveralls.io/repos/github/passport-next/passport/badge.svg?branch=master)](https://coveralls.io/github/passport-next/passport?branch=master) | ||
[![Maintainability](https://api.codeclimate.com/v1/badges/deaf381bf0cff6bf26a5/maintainability)](https://codeclimate.com/github/passport-next/passport/maintainability) | ||
[![Dependencies](https://david-dm.org/passport-next/passport.png)](https://david-dm.org/passport-next/passport) | ||
[![SAST](https://gitlab.com/passport-next/passport/badges/master/pipeline.svg)](https://gitlab.com/passport-next/passport) | ||
## About | ||
Passport-Next/Passport is [Express](http://expressjs.com/)-compatible authentication | ||
@@ -13,34 +23,3 @@ middleware for [Node.js](http://nodejs.org/). | ||
Status: | ||
[![NPM version](https://img.shields.io/npm/v/@passport-next/passport.svg)](https://www.npmjs.com/package/@passport-next/passport) | ||
[![Build Status](https://travis-ci.org/passport-next/passport.svg?branch=master)](https://travis-ci.org/passport-next/passport) | ||
[![Coverage Status](https://coveralls.io/repos/github/passport-next/passport/badge.svg?branch=master)](https://coveralls.io/github/passport-next/passport?branch=master) | ||
[![Maintainability](https://api.codeclimate.com/v1/badges/deaf381bf0cff6bf26a5/maintainability)](https://codeclimate.com/github/passport-next/passport/maintainability) | ||
[![Dependencies](https://david-dm.org/passport-next/passport.png)](https://david-dm.org/passport-next/passport) | ||
[![SAST](https://gitlab.com/passport-next/passport/badges/master/build.svg)](https://gitlab.com/passport-next/passport/badges/master/build.svg) | ||
## Differences between passport and passport-next | ||
[Passport Next](https://github.com/passport-next) was created as a fork of the Passport repositories | ||
when the upstream repositories became stale and stopped working due to changes at the various | ||
authentication providers (e.g. Facebook API deprecation, Tumblr using HTTPS etc.) | ||
Passport Next aims to: | ||
* Keep the modules up to date with the various authentication providers | ||
* Maintain up to date dependencies | ||
* Address any security issues promptly | ||
* Ensure compatibility with the current [supported versions](https://github.com/nodejs/Release) of Node | ||
* Maintain the repositories in an organisation so maintaining isn't the responsibility of one person | ||
* Follow [Semantic Versioning](https://semver.org/) | ||
* Keep an up to date CHANGELOG.md | ||
**Passport Next does not aim to be backwards compatible with the upstream repositories. | ||
The changes required to keep up to date and functioning prohibit that so if you're migrating | ||
from the upstream modules please test your code thouroughly!** | ||
If you wish to join the team please raise an issue and one of the maintainers will assess your | ||
request. | ||
## Install | ||
@@ -52,147 +31,19 @@ | ||
## Usage | ||
## Docs | ||
#### Strategies | ||
[Please see the wiki](https://github.com/passport-next/passport/wiki) | ||
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/). | ||
## Need help? | ||
Before authenticating requests, the strategy (or strategies) used by an | ||
application must be configured. | ||
Please raise an [issue](https://github.com/passport-next/passport/issues) and/or ask a question on [Stackoverflow](https://stackoverflow.com) with the `passport.js` tag. | ||
```javascript | ||
passport.use(new LocalStrategy( | ||
function(username, password, done) { | ||
User.findOne({ username: username }, function (err, user) { | ||
if (err) { return done(err); } | ||
if (!user) { return done(null, false); } | ||
if (!user.verifyPassword(password)) { return done(null, false); } | ||
return done(null, user); | ||
}); | ||
} | ||
)); | ||
``` | ||
## Support policy | ||
There are 480+ strategies. Find the ones you want at: [passportjs.org](http://passportjs.org) | ||
We support all [node versions](https://github.com/nodejs/Release) supported by the Node Foundation | ||
#### 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. | ||
## Contributing | ||
```javascript | ||
passport.serializeUser(function(user, done) { | ||
done(null, user.id); | ||
}); | ||
Please see [CONTRIBUTING.md](https://github.com/passport-next/passport/blob/master/CONTRIBUTING.md) | ||
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. | ||
```javascript | ||
var app = express(); | ||
app.use(require('serve-static')(__dirname + '/../../public')); | ||
app.use(require('cookie-parser')()); | ||
app.use(require('body-parser').urlencoded({ extended: true })); | ||
app.use(require('express-session')({ secret: 'keyboard cat', resave: true, saveUninitialized: true })); | ||
app.use(passport.initialize()); | ||
app.use(passport.session()); | ||
``` | ||
#### Authenticate Requests | ||
Passport provides an `authenticate()` function, which is used as route | ||
middleware to authenticate requests. | ||
```javascript | ||
app.post('/login', | ||
passport.authenticate('local', { failureRedirect: '/login' }), | ||
function(req, res) { | ||
res.redirect('/'); | ||
}); | ||
``` | ||
#### Protect Routes When Using Sessions | ||
Passport provides an `isAuthenticated()` function on the request object, which | ||
is used to determine if the user has been authenticated and stored in the | ||
session. | ||
```javascript | ||
app.post('/some/protected/route', | ||
function(req, res, next) { | ||
if(req.isAuthenticated()){ | ||
next(); | ||
} else { | ||
next(new Error('Unauthorized')); | ||
} | ||
}); | ||
``` | ||
For a more complete solution to handling unauthenticated users, see | ||
[connect-ensure-login](https://github.com/jaredhanson/connect-ensure-login), a | ||
middleware to ensure login sessions. | ||
## Strategies | ||
Passport has a comprehensive set of **over 480** authentication strategies | ||
covering social networking, enterprise integration, API services, and more. | ||
## Search all strategies | ||
There is a **Strategy Search** at [passportjs.org](http://passportjs.org) | ||
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) | | ||
|[Azure Active Directory](https://github.com/AzureAD/passport-azure-ad) | OAuth 2.0 / OpenID / SAML |[Azure](https://github.com/azuread) | | ||
## Examples | ||
- For a complete, working example, refer to the [example](https://github.com/passport/express-4.x-local-example) | ||
that uses [passport-local](https://github.com/jaredhanson/passport-local). | ||
- **Local Strategy**: Refer to the following tutorials for setting up user authentication via LocalStrategy (`passport-local`): | ||
- Mongo | ||
- Express v3x - [Tutorial](http://mherman.org/blog/2016/09/25/node-passport-and-postgres/#.V-govpMrJE5) / [working example](https://github.com/mjhea0/passport-local-knex) | ||
- Express v4x - [Tutorial](http://mherman.org/blog/2015/01/31/local-authentication-with-passport-and-express-4/) / [working example](https://github.com/mjhea0/passport-local-express4) | ||
- Postgres | ||
- [Tutorial](http://mherman.org/blog/2016/09/25/node-passport-and-postgres/) / [working example](https://github.com/mjhea0/passport-local-knex) | ||
- Koa - [Tutorial](http://mherman.org/blog/2018/01/02/user-authentication-with-passport-and-koa) / [working example](https://github.com/mjhea0/node-koa-api) | ||
- **Social Authentication**: Refer to the following tutorials for setting up various social authentication strategies: | ||
- Express v3x - [Tutorial](http://mherman.org/blog/2013/11/10/social-authentication-with-passport-dot-js/) / [working example](https://github.com/mjhea0/passport-examples) | ||
- Express v4x - [Tutorial](http://mherman.org/blog/2015/09/26/social-authentication-in-node-dot-js-with-passport) / [working example](https://github.com/mjhea0/passport-social-auth) | ||
## Tests | ||
``` | ||
$ npm install | ||
$ make test | ||
``` |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
123730
30
1529
0
22
48