Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jaredhanson/passport
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 42ff63c60ae55f466d21332306e9112295c0535e
Choose a base ref
...
head repository: jaredhanson/passport
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: c33067bc5aa81a6dd827076d810bf788bb6acac7
Choose a head ref
Loading
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
github: jaredhanson
patreon: jaredhanson
ko_fi: jaredhanson
42 changes: 42 additions & 0 deletions .github/workflows/node.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions

name: Node.js CI

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
build:

runs-on: ubuntu-latest

strategy:
matrix:
node-version:
- '17'
- '16'
- '14'
- '12'
- '10'
- '8'
- '6'
- '4'
# - '3' # io.js
# - '2' # io.js
# - '1' # io.js
- '0.12'
- '0.10'
# - '0.8'

steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm test
64 changes: 64 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Changelog
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.6.0] - 2022-05-20
### Security

- Improved robustness against session fixation attacks in cases where there is
physical access to the same system or the application is susceptible to
cross-site scripting (XSS).

## [0.5.3] - 2022-05-16
### Fixed

- `initialize()` middleware extends request with `login()`, `logIn()`,
`logout()`, `logOut()`, `isAuthenticated()`, and `isUnauthenticated()` functions
again, reverting change from 0.5.1.

## [0.5.2] - 2021-12-16
### Fixed
- Introduced a compatibility layer for strategies that depend directly on
`passport@0.4.x` or earlier (such as `passport-azure-ad`), which were
broken by the removal of private variables in `passport@0.5.1`.

## [0.5.1] - 2021-12-15
### Added
- Informative error message in session strategy if session support is not
available.

### Changed

- `authenticate()` middleware, rather than `initialize()` middleware, extends
request with `login()`, `logIn()`, `logout()`, `logOut()`, `isAuthenticated()`,
and `isUnauthenticated()` functions.

## [0.5.0] - 2021-09-23
### Changed

- `initialize()` middleware extends request with `login()`, `logIn()`,
`logout()`, `logOut()`, `isAuthenticated()`, and `isUnauthenticated()`
functions.

### Removed

- `login()`, `logIn()`, `logout()`, `logOut()`, `isAuthenticated()`, and
`isUnauthenticated()` functions no longer added to `http.IncomingMessage.prototype`.

### Fixed

- `userProperty` option to `initialize()` middleware only affects the current
request, rather than all requests processed via singleton Passport instance,
eliminating a race condition in situations where `initialize()` middleware is
used multiple times in an application with `userProperty` set to different
values.

[Unreleased]: https://github.com/jaredhanson/passport/compare/v0.6.0...HEAD
[0.6.0]: https://github.com/jaredhanson/passport/compare/v0.5.3...v0.6.0
[0.5.3]: https://github.com/jaredhanson/passport/compare/v0.5.2...v0.5.3
[0.5.2]: https://github.com/jaredhanson/passport/compare/v0.5.1...v0.5.2
[0.5.1]: https://github.com/jaredhanson/passport/compare/v0.5.0...v0.5.1
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2011-2019 Jared Hanson
Copyright (c) 2011-2021 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
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -12,6 +12,19 @@ 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.

---

<p align="center">
<sup>Sponsors</sup>
<br>
<a href="https://workos.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=passport_js&utm_source=github"><img src="https://raw.githubusercontent.com/jaredhanson/passport/master/sponsors/workos.png"></a><br/>
<a href="https://workos.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=passport_js&utm_source=github"><b>Your app, enterprise-ready.</b><br/>Start selling to enterprise customers with just a few lines of code. Add Single Sign-On (and more) in minutes instead of months.</a>
<br>
<a href="https://snyk.co/passport"><img src="https://raw.githubusercontent.com/jaredhanson/passport/master/sponsors/snyk.png" width="301" height="171"></a><br/>
</p>

---

Status:
[![Build](https://travis-ci.org/jaredhanson/passport.svg?branch=master)](https://travis-ci.org/jaredhanson/passport)
[![Coverage](https://coveralls.io/repos/jaredhanson/passport/badge.svg?branch=master)](https://coveralls.io/r/jaredhanson/passport)
@@ -157,4 +170,4 @@ that build upon or integrate with Passport.

[The MIT License](http://opensource.org/licenses/MIT)

Copyright (c) 2011-2019 Jared Hanson <[http://jaredhanson.net/](http://jaredhanson.net/)>
Copyright (c) 2011-2021 Jared Hanson <[https://www.jaredhanson.me/](https://www.jaredhanson.me/)>
13 changes: 13 additions & 0 deletions SPONSORS.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
## Gold Sponsors

[![WorkOS](https://raw.githubusercontent.com/jaredhanson/passport/master/sponsors/workos.png)](https://workos.com/)
<br>
[![Snyk](https://raw.githubusercontent.com/jaredhanson/passport/master/sponsors/snyk.png)](https://snyk.io/)

## Sponsors

- [CodePilot.ai](https://codepilot.ai/)
- [Jeremy Combs](https://github.com/jmcombs)
- [Gadget](https://gadget.dev/)
- Kelly Burke
- [Matt Miller](https://mmiller.me/)

## Past Sponsors

- [LoginRadius](https://www.loginradius.com/)
5 changes: 1 addition & 4 deletions lib/authenticator.js
Original file line number Diff line number Diff line change
@@ -17,7 +17,6 @@ function Authenticator() {
this._deserializers = [];
this._infoTransformers = [];
this._framework = null;
this._userProperty = 'user';

this.init();
}
@@ -29,7 +28,7 @@ function Authenticator() {
*/
Authenticator.prototype.init = function() {
this.framework(require('./framework/connect')());
this.use(new SessionStrategy(this.deserializeUser.bind(this)));
this.use(new SessionStrategy({ key: this._key }, this.deserializeUser.bind(this)));
this._sm = new SessionManager({ key: this._key }, this.serializeUser.bind(this));
};

@@ -128,8 +127,6 @@ Authenticator.prototype.framework = function(fw) {
*/
Authenticator.prototype.initialize = function(options) {
options = options || {};
this._userProperty = options.userProperty || 'user';

return this._framework.initialize(this, options);
};

19 changes: 1 addition & 18 deletions lib/framework/connect.js
Original file line number Diff line number Diff line change
@@ -8,32 +8,15 @@ var initialize = require('../middleware/initialize')
* Framework support for Connect/Express.
*
* This module provides support for using Passport with Express. It exposes
* middleware that conform to the `fn(req, res, next)` signature and extends
* Node's built-in HTTP request object with useful authentication-related
* functions.
* middleware that conform to the `fn(req, res, next)` signature.
*
* @return {Object}
* @api protected
*/
exports = module.exports = function() {

// HTTP extensions.
exports.__monkeypatchNode();

return {
initialize: initialize,
authenticate: authenticate
};
};

exports.__monkeypatchNode = function() {
var http = require('http');
var IncomingMessageExt = require('../http/request');

http.IncomingMessage.prototype.login =
http.IncomingMessage.prototype.logIn = IncomingMessageExt.logIn;
http.IncomingMessage.prototype.logout =
http.IncomingMessage.prototype.logOut = IncomingMessageExt.logOut;
http.IncomingMessage.prototype.isAuthenticated = IncomingMessageExt.isAuthenticated;
http.IncomingMessage.prototype.isUnauthenticated = IncomingMessageExt.isUnauthenticated;
};
42 changes: 17 additions & 25 deletions lib/http/request.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
/**
* Module dependencies.
*/
//var http = require('http')
// , req = http.IncomingMessage.prototype;


var req = exports = module.exports = {};

/**
@@ -35,19 +28,15 @@ req.logIn = function(user, options, done) {
}
options = options || {};

var property = 'user';
if (this._passport && this._passport.instance) {
property = this._passport.instance._userProperty || 'user';
}
var property = this._userProperty || 'user';
var session = (options.session === undefined) ? true : options.session;

this[property] = user;
if (session) {
if (!this._passport) { throw new Error('passport.initialize() middleware not in use'); }
if (session && this._sessionManager) {
if (typeof done != 'function') { throw new Error('req#login requires a callback function'); }

var self = this;
this._passport.instance._sm.logIn(this, user, function(err) {
this._sessionManager.logIn(this, user, options, function(err) {
if (err) { self[property] = null; return done(err); }
done();
});
@@ -62,15 +51,22 @@ req.logIn = function(user, options, done) {
* @api public
*/
req.logout =
req.logOut = function() {
var property = 'user';
if (this._passport && this._passport.instance) {
property = this._passport.instance._userProperty || 'user';
req.logOut = function(options, done) {
if (typeof options == 'function') {
done = options;
options = {};
}
options = options || {};

var property = this._userProperty || 'user';

this[property] = null;
if (this._passport) {
this._passport.instance._sm.logOut(this);
if (this._sessionManager) {
if (typeof done != 'function') { throw new Error('req#logout requires a callback function'); }

this._sessionManager.logOut(this, options, done);
} else {
done && done();
}
};

@@ -81,11 +77,7 @@ req.logOut = function() {
* @api public
*/
req.isAuthenticated = function() {
var property = 'user';
if (this._passport && this._passport.instance) {
property = this._passport.instance._userProperty || 'user';
}

var property = this._userProperty || 'user';
return (this[property]) ? true : false;
};

11 changes: 7 additions & 4 deletions lib/middleware/authenticate.js
Original file line number Diff line number Diff line change
@@ -92,11 +92,14 @@ module.exports = function authenticate(passport, name, options, callback) {
}

return function authenticate(req, res, next) {
if (http.IncomingMessage.prototype.logIn
&& http.IncomingMessage.prototype.logIn !== IncomingMessageExt.logIn) {
require('../framework/connect').__monkeypatchNode();
}
req.login =
req.logIn = req.logIn || IncomingMessageExt.logIn;
req.logout =
req.logOut = req.logOut || IncomingMessageExt.logOut;
req.isAuthenticated = req.isAuthenticated || IncomingMessageExt.isAuthenticated;
req.isUnauthenticated = req.isUnauthenticated || IncomingMessageExt.isUnauthenticated;

req._sessionManager = passport._sm;

// accumulator for failures from each strategy in the chain
var failures = [];
61 changes: 53 additions & 8 deletions lib/middleware/initialize.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
/**
* Module dependencies.
*/
var IncomingMessageExt = require('../http/request');


/**
* Passport initialization.
*
@@ -39,17 +45,56 @@
* @return {Function}
* @api public
*/
module.exports = function initialize(passport) {
module.exports = function initialize(passport, options) {
options = options || {};

return function initialize(req, res, next) {
req._passport = {};
req._passport.instance = passport;

if (req.session && req.session[passport._key]) {
// load data from existing session
req._passport.session = req.session[passport._key];
req.login =
req.logIn = req.logIn || IncomingMessageExt.logIn;
req.logout =
req.logOut = req.logOut || IncomingMessageExt.logOut;
req.isAuthenticated = req.isAuthenticated || IncomingMessageExt.isAuthenticated;
req.isUnauthenticated = req.isUnauthenticated || IncomingMessageExt.isUnauthenticated;

req._sessionManager = passport._sm;

if (options.userProperty) {
req._userProperty = options.userProperty;
}


var compat = (options.compat === undefined) ? true : options.compat;
if (compat) {
// `passport@0.5.1` [removed][1] all internal use of `req._passport`.
// From the standpoint of this package, this should have been a
// non-breaking change. However, some strategies (such as `passport-azure-ad`)
// depend directly on `passport@0.4.x` or earlier. `require`-ing earlier
// versions of `passport` has the effect of monkeypatching `http.IncomingMessage`
// with `logIn`, `logOut`, `isAuthenticated` and `isUnauthenticated`
// functions that [expect][2] the `req._passport` property to exist.
// Since pre-existing functions on `req` are given [preference][3], this
// results in [issues][4].
//
// The changes here restore the expected properties needed when earlier
// versions of `passport` are `require`-ed. This compatibility mode is
// enabled by default, and can be disabld by simply not `use`-ing `passport.initialize()`
// middleware or setting `compat: false` as an option to the middleware.
//
// An alternative approach to addressing this issue would be to not
// preferentially use pre-existing functions on `req`, but rather always
// overwrite `req.logIn`, etc. with the versions of those functions shiped
// with `authenticate()` middleware. This option should be reconsidered
// in a future major version release.
//
// [1]: https://github.com/jaredhanson/passport/pull/875
// [2]: https://github.com/jaredhanson/passport/blob/v0.4.1/lib/http/request.js
// [3]: https://github.com/jaredhanson/passport/blob/v0.5.1/lib/middleware/authenticate.js#L96
// [4]: https://github.com/jaredhanson/passport/issues/877
passport._userProperty = options.userProperty || 'user';

req._passport = {};
req._passport.instance = passport;
}

next();
};
};
Loading