passport-oauth2
Advanced tools
Comparing version 1.2.0 to 1.3.0
@@ -25,6 +25,6 @@ /** | ||
} | ||
Error.call(this); | ||
Error.captureStackTrace(this, arguments.callee); | ||
this.name = 'AuthorizationError'; | ||
Error.captureStackTrace(this, this.constructor); | ||
this.name = this.constructor.name; | ||
this.message = message; | ||
@@ -31,0 +31,0 @@ this.code = code || 'server_error'; |
@@ -15,4 +15,4 @@ /** | ||
Error.call(this); | ||
Error.captureStackTrace(this, arguments.callee); | ||
this.name = 'InternalOAuthError'; | ||
Error.captureStackTrace(this, this.constructor); | ||
this.name = this.constructor.name; | ||
this.message = message; | ||
@@ -19,0 +19,0 @@ this.oauthError = err; |
@@ -19,4 +19,4 @@ /** | ||
Error.call(this); | ||
Error.captureStackTrace(this, arguments.callee); | ||
this.name = 'TokenError'; | ||
Error.captureStackTrace(this, this.constructor); | ||
this.name = this.constructor.name; | ||
this.message = message; | ||
@@ -23,0 +23,0 @@ this.code = code || 'invalid_request'; |
@@ -1,4 +0,2 @@ | ||
/** | ||
* Module dependencies. | ||
*/ | ||
// Load modules. | ||
var Strategy = require('./strategy') | ||
@@ -10,17 +8,10 @@ , AuthorizationError = require('./errors/authorizationerror') | ||
/** | ||
* Expose `Strategy` directly from package. | ||
*/ | ||
// Expose Strategy. | ||
exports = module.exports = Strategy; | ||
/** | ||
* Export constructors. | ||
*/ | ||
// Exports. | ||
exports.Strategy = Strategy; | ||
/** | ||
* Export errors. | ||
*/ | ||
exports.AuthorizationError = AuthorizationError; | ||
exports.TokenError = TokenError; | ||
exports.InternalOAuthError = InternalOAuthError; |
var uid = require('uid2'); | ||
/** | ||
* Creates an instance of `SessionStateProvider`. | ||
* Creates an instance of `SessionStore`. | ||
* | ||
* This is the default state provider implementation for the OAuth2Strategy. | ||
* If generates a random state and stores it in `req.session` under the `key` | ||
* provided in the constructor. | ||
* This is the state store implementation for the OAuth2Strategy used when | ||
* the `state` option is enabled. It generates a random state and stores it in | ||
* `req.session` and verifies it when the service provider redirects the user | ||
* back to the application. | ||
* | ||
* If no session exists, the provider will throw an error. If you are not using | ||
* sessions, consider using `TokenStateProvider` instead. | ||
* This state store requires session support. If no session exists, an error | ||
* will be thrown. | ||
* | ||
* Options: | ||
* | ||
* - `key` The key in the session under which to store the session state | ||
* - `key` The key in the session under which to store the state | ||
* | ||
@@ -22,3 +23,3 @@ * @constructor | ||
function SessionStore(options) { | ||
if (!options.key) { throw new TypeError('SessionStateStore requires a key'); } | ||
if (!options.key) { throw new TypeError('Session-based state store requires a session key'); } | ||
this._key = options.key; | ||
@@ -28,6 +29,7 @@ } | ||
/** | ||
* Given a request, returns a value to use as state. | ||
* Store request state. | ||
* | ||
* This implementation simply generates a random UID and stores the value in the session | ||
* for validation at a later stage when `verify` is called. | ||
* This implementation simply generates a random string and stores the value in | ||
* the session, where it will be used for verification when the user is | ||
* redirected back to the application. | ||
* | ||
@@ -39,3 +41,3 @@ * @param {Object} req | ||
SessionStore.prototype.store = function(req, callback) { | ||
if (!req.session) { return callback(new Error('OAuth2Strategy requires session support when using state. Did you forget app.use(express.session(...))?')); } | ||
if (!req.session) { return callback(new Error('OAuth 2.0 authentication requires session support when using state. Did you forget to use express-session middleware?')); } | ||
@@ -50,12 +52,7 @@ var key = this._key; | ||
/** | ||
* Given a request, and the state returned by the OAuth provider, verifies the state. | ||
* Verify request state. | ||
* | ||
* This implementation simply compares the returned state to the one saved in the user's session. | ||
* If they do not match, or no state is saved in the session, the call will fail. | ||
* If there is no session, the call will return an error. | ||
* This implementation simply compares the state parameter in the request to the | ||
* value generated earlier and stored in the session. | ||
* | ||
* The callback signature has two values (`err`, `failureCode`). On success, these are both | ||
* undefined. On error, only `err` is definied and on failure, err will contain the failure object | ||
* while `failureCode` will contain the failure code. | ||
* | ||
* @param {Object} req | ||
@@ -67,3 +64,3 @@ * @param {String} providedState | ||
SessionStore.prototype.verify = function(req, providedState, callback) { | ||
if (!req.session) { return callback(new Error('OAuth2Strategy requires session support when using state. Did you forget app.use(express.session(...))?')); } | ||
if (!req.session) { return callback(new Error('OAuth 2.0 authentication requires session support when using state. Did you forget to use express-session middleware?')); } | ||
@@ -92,5 +89,3 @@ var key = this._key; | ||
/** | ||
* Expose `SessionStateProvider`. | ||
*/ | ||
// Expose constructor. | ||
module.exports = SessionStore; |
@@ -1,4 +0,2 @@ | ||
/** | ||
* Module dependencies. | ||
*/ | ||
// Load modules. | ||
var passport = require('passport-strategy') | ||
@@ -85,3 +83,2 @@ , url = require('url') | ||
if (!options.clientID) { throw new TypeError('OAuth2Strategy requires a clientID option'); } | ||
if (!options.clientSecret) { throw new TypeError('OAuth2Strategy requires a clientSecret option'); } | ||
@@ -117,5 +114,3 @@ passport.Strategy.call(this); | ||
/** | ||
* Inherit from `passport.Strategy`. | ||
*/ | ||
// Inherit from `passport.Strategy`. | ||
util.inherits(OAuth2Strategy, passport.Strategy); | ||
@@ -151,11 +146,16 @@ | ||
} | ||
var meta = { | ||
authorizationURL: this._oauth2._authorizeUrl, | ||
tokenURL: this._oauth2._accessTokenUrl, | ||
clientID: this._oauth2._clientId | ||
} | ||
if (req.query && req.query.code) { | ||
var state = req.query.state; | ||
this._stateStore.verify(req, state, function(err, ok, info) { | ||
function loaded(err, ok, state) { | ||
if (err) { return self.error(err); } | ||
if (!ok) { | ||
return self.fail(info, 403); | ||
return self.fail(state, 403); | ||
} | ||
var code = req.query.code; | ||
@@ -165,3 +165,3 @@ | ||
params.grant_type = 'authorization_code'; | ||
params.redirect_uri = callbackURL; | ||
if (callbackURL) { params.redirect_uri = callbackURL; } | ||
@@ -178,2 +178,5 @@ self._oauth2.getOAuthAccessToken(code, params, | ||
if (!user) { return self.fail(info); } | ||
info = info || {}; | ||
if (state) { info.state = state; } | ||
self.success(user, info); | ||
@@ -204,7 +207,19 @@ } | ||
); | ||
}); | ||
} | ||
var state = req.query.state; | ||
try { | ||
var arity = this._stateStore.verify.length; | ||
if (arity == 4) { | ||
this._stateStore.verify(req, state, meta, loaded); | ||
} else { // arity == 3 | ||
this._stateStore.verify(req, state, loaded); | ||
} | ||
} catch (ex) { | ||
return this.error(ex); | ||
} | ||
} else { | ||
var params = this.authorizationParams(options); | ||
params.response_type = 'code'; | ||
params.redirect_uri = callbackURL; | ||
if (callbackURL) { params.redirect_uri = callbackURL; } | ||
var scope = options.scope || this._scope; | ||
@@ -222,3 +237,3 @@ if (scope) { | ||
} else { | ||
this._stateStore.store(req, function(err, state) { | ||
function stored(err, state) { | ||
if (err) { return self.error(err); } | ||
@@ -229,3 +244,14 @@ | ||
self.redirect(location); | ||
}); | ||
} | ||
try { | ||
var arity = this._stateStore.store.length; | ||
if (arity == 3) { | ||
this._stateStore.store(req, meta, stored); | ||
} else { // arity == 2 | ||
this._stateStore.store(req, stored); | ||
} | ||
} catch (ex) { | ||
return this.error(ex); | ||
} | ||
} | ||
@@ -357,5 +383,3 @@ } | ||
/** | ||
* Expose `OAuth2Strategy`. | ||
*/ | ||
// Expose constructor. | ||
module.exports = OAuth2Strategy; |
{ | ||
"name": "passport-oauth2", | ||
"version": "1.2.0", | ||
"version": "1.3.0", | ||
"description": "OAuth 2.0 authentication strategy for Passport.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
# passport-oauth2 | ||
[![Build](https://travis-ci.org/jaredhanson/passport-oauth2.svg?branch=master)](https://travis-ci.org/jaredhanson/passport-oauth2) | ||
[![Coverage](https://coveralls.io/repos/jaredhanson/passport-oauth2/badge.svg?branch=master)](https://coveralls.io/r/jaredhanson/passport-oauth2) | ||
[![Quality](https://codeclimate.com/github/jaredhanson/passport-oauth2/badges/gpa.svg)](https://codeclimate.com/github/jaredhanson/passport-oauth2) | ||
[![Dependencies](https://david-dm.org/jaredhanson/passport-oauth2.svg)](https://david-dm.org/jaredhanson/passport-oauth2) | ||
[![Tips](https://img.shields.io/gratipay/jaredhanson.svg)](https://gratipay.com/jaredhanson/) | ||
[![Build](https://img.shields.io/travis/jaredhanson/passport-oauth2.svg)](https://travis-ci.org/jaredhanson/passport-oauth2) | ||
[![Coverage](https://img.shields.io/coveralls/jaredhanson/passport-oauth2.svg)](https://coveralls.io/r/jaredhanson/passport-oauth2) | ||
[![Quality](https://img.shields.io/codeclimate/github/jaredhanson/passport-oauth2.svg?label=quality)](https://codeclimate.com/github/jaredhanson/passport-oauth2) | ||
[![Dependencies](https://img.shields.io/david/jaredhanson/passport-oauth2.svg)](https://david-dm.org/jaredhanson/passport-oauth2) | ||
@@ -41,3 +40,3 @@ | ||
requires a `verify` callback, which receives an access token and profile, | ||
and calls `done` providing a user. | ||
and calls `cb` providing a user. | ||
@@ -52,5 +51,5 @@ ```js | ||
}, | ||
function(accessToken, refreshToken, profile, done) { | ||
function(accessToken, refreshToken, profile, cb) { | ||
User.findOrCreate({ exampleId: profile.id }, function (err, user) { | ||
return done(err, user); | ||
return cb(err, user); | ||
}); | ||
@@ -87,13 +86,38 @@ } | ||
## Tests | ||
## Contributing | ||
#### Tests | ||
The test suite is located in the `test/` directory. All new features are | ||
expected to have corresponding test cases. Ensure that the complete test suite | ||
passes by executing: | ||
```bash | ||
$ make test | ||
``` | ||
$ npm install | ||
$ npm test | ||
#### Coverage | ||
All new feature development is expected to have test coverage. Patches that | ||
increse test coverage are happily accepted. Coverage reports can be viewed by | ||
executing: | ||
```bash | ||
$ make test-cov | ||
$ make view-cov | ||
``` | ||
## Credits | ||
## Support | ||
- [Jared Hanson](http://github.com/jaredhanson) | ||
#### Funding | ||
This software is provided to you as open source, free of charge. The time and | ||
effort to develop and maintain this project is dedicated by [@jaredhanson](https://github.com/jaredhanson). | ||
If you (or your employer) benefit from this project, please consider a financial | ||
contribution. Your contribution helps continue the efforts that produce this | ||
and other open source software. | ||
Funds are accepted via [PayPal](https://paypal.me/jaredhanson), [Venmo](https://venmo.com/jaredhanson), | ||
and [other](http://jaredhanson.net/pay) methods. Any amount is appreciated. | ||
## License | ||
@@ -103,2 +127,2 @@ | ||
Copyright (c) 2011-2015 Jared Hanson <[http://jaredhanson.net/](http://jaredhanson.net/)> | ||
Copyright (c) 2011-2016 Jared Hanson <[http://jaredhanson.net/](http://jaredhanson.net/)> |
26617
584
125