pax_global_header 0000666 0000000 0000000 00000000064 11735720171 0014516 g ustar 00root root 0000000 0000000 52 comment=6b91df763721dc9addac8ed297f48b9cc6819751
jaredhanson-passport-oauth-e7afa47/ 0000775 0000000 0000000 00000000000 11735720171 0017501 5 ustar 00root root 0000000 0000000 jaredhanson-passport-oauth-e7afa47/.gitignore 0000664 0000000 0000000 00000000027 11735720171 0021470 0 ustar 00root root 0000000 0000000 .DS_Store
node_modules
jaredhanson-passport-oauth-e7afa47/.npmignore 0000664 0000000 0000000 00000000075 11735720171 0021502 0 ustar 00root root 0000000 0000000 *.md
.DS_Store
.git*
Makefile
docs/
examples/
support/
test/
jaredhanson-passport-oauth-e7afa47/.travis.yml 0000664 0000000 0000000 00000000055 11735720171 0021612 0 ustar 00root root 0000000 0000000 language: "node_js"
node_js:
- 0.4
- 0.6
jaredhanson-passport-oauth-e7afa47/LICENSE 0000664 0000000 0000000 00000002063 11735720171 0020507 0 ustar 00root root 0000000 0000000 (The MIT License)
Copyright (c) 2011 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.
jaredhanson-passport-oauth-e7afa47/Makefile 0000664 0000000 0000000 00000000657 11735720171 0021151 0 ustar 00root root 0000000 0000000 NODE = node
TEST = ./node_modules/.bin/vows
TESTS ?= test/*-test.js test/**/*-test.js
test:
@NODE_ENV=test NODE_PATH=lib $(TEST) $(TEST_FLAGS) $(TESTS)
docs: docs/api.html
docs/api.html: lib/passport-oauth/*.js
dox \
--title Passport-OAuth \
--desc "OAuth 1.0 and 2.0 authentication strategies for Passport" \
$(shell find lib/passport-oauth/* -type f) > $@
docclean:
rm -f docs/*.{1,html}
.PHONY: test docs docclean
jaredhanson-passport-oauth-e7afa47/README.md 0000664 0000000 0000000 00000012534 11735720171 0020765 0 ustar 00root root 0000000 0000000 # Passport-OAuth
General-purpose OAuth 1.0 and OAuth 2.0 authentication strategies for [Passport](https://github.com/jaredhanson/passport).
## Installation
$ npm install passport-oauth
## Strategies using OAuth
## Tests
$ npm install --dev
$ make test
[](http://travis-ci.org/jaredhanson/passport-oauth)
## Credits
- [Jared Hanson](http://github.com/jaredhanson)
## License
(The MIT License)
Copyright (c) 2011 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.
jaredhanson-passport-oauth-e7afa47/lib/ 0000775 0000000 0000000 00000000000 11735720171 0020247 5 ustar 00root root 0000000 0000000 jaredhanson-passport-oauth-e7afa47/lib/passport-oauth/ 0000775 0000000 0000000 00000000000 11735720171 0023240 5 ustar 00root root 0000000 0000000 jaredhanson-passport-oauth-e7afa47/lib/passport-oauth/errors/ 0000775 0000000 0000000 00000000000 11735720171 0024554 5 ustar 00root root 0000000 0000000 jaredhanson-passport-oauth-e7afa47/lib/passport-oauth/errors/internaloautherror.js 0000664 0000000 0000000 00000002071 11735720171 0031041 0 ustar 00root root 0000000 0000000 /**
* `InternalOAuthError` error.
*
* InternalOAuthError wraps errors generated by node-oauth. By wrapping these
* objects, error messages can be formatted in a manner that aids in debugging
* OAuth issues.
*
* @api public
*/
function InternalOAuthError(message, err) {
Error.call(this);
Error.captureStackTrace(this, arguments.callee);
this.name = 'InternalOAuthError';
this.message = message;
this.oauthError = err;
};
/**
* Inherit from `Error`.
*/
InternalOAuthError.prototype.__proto__ = Error.prototype;
/**
* Returns a string representing the error.
*
* @return {String}
* @api public
*/
InternalOAuthError.prototype.toString = function() {
var m = this.message;
if (this.oauthError) {
if (this.oauthError instanceof Error) {
m += ' (' + this.oauthError + ')';
}
else if (this.oauthError.statusCode && this.oauthError.data) {
m += ' (status: ' + this.oauthError.statusCode + ' data: ' + this.oauthError.data + ')';
}
}
return m;
}
/**
* Expose `InternalOAuthError`.
*/
module.exports = InternalOAuthError;
jaredhanson-passport-oauth-e7afa47/lib/passport-oauth/index.js 0000664 0000000 0000000 00000000663 11735720171 0024712 0 ustar 00root root 0000000 0000000 /**
* Module dependencies.
*/
var OAuthStrategy = require('./strategies/oauth');
var OAuth2Strategy = require('./strategies/oauth2');
var InternalOAuthError = require('./errors/internaloautherror');
/**
* Framework version.
*/
require('pkginfo')(module, 'version');
/**
* Expose constructors.
*/
exports.OAuthStrategy = OAuthStrategy;
exports.OAuth2Strategy = OAuth2Strategy;
exports.InternalOAuthError = InternalOAuthError;
jaredhanson-passport-oauth-e7afa47/lib/passport-oauth/strategies/ 0000775 0000000 0000000 00000000000 11735720171 0025412 5 ustar 00root root 0000000 0000000 jaredhanson-passport-oauth-e7afa47/lib/passport-oauth/strategies/oauth.js 0000664 0000000 0000000 00000023673 11735720171 0027103 0 ustar 00root root 0000000 0000000 /**
* Module dependencies.
*/
var passport = require('passport')
, url = require('url')
, util = require('util')
, OAuth = require('oauth').OAuth
, InternalOAuthError = require('../errors/internaloautherror');
/**
* `OAuthStrategy` constructor.
*
* The OAuth authentication strategy authenticates requests using the OAuth
* protocol.
*
* OAuth provides a facility for delegated authentication, whereby users can
* authenticate using a third-party service such as Twitter. Delegating in this
* manner involves a sequence of events, including redirecting the user to the
* third-party service for authorization. Once authorization has been obtained,
* the user is redirected back to the application and a token can be used to
* obtain credentials.
*
* Applications must supply a `verify` callback which accepts a `token`,
* `tokenSecret` and service-specific `profile`, and then calls the `done`
* callback supplying a `user`, which should be set to `false` if the
* credentials are not valid. If an exception occured, `err` should be set.
*
* Options:
* - `requestTokenURL` URL used to obtain an unauthorized request token
* - `accessTokenURL` URL used to exchange a user-authorized request token for an access token
* - `userAuthorizationURL` URL used to obtain user authorization
* - `consumerKey` identifies client to service provider
* - `consumerSecret` secret used to establish ownership of the consumer key
* - `callbackURL` URL to which the service provider will redirect the user after obtaining authorization
*
* Examples:
*
* passport.use(new OAuthStrategy({
* requestTokenURL: 'https://www.example.com/oauth/request_token',
* accessTokenURL: 'https://www.example.com/oauth/access_token',
* userAuthorizationURL: 'https://www.example.com/oauth/authorize',
* consumerKey: '123-456-789',
* consumerSecret: 'shhh-its-a-secret'
* callbackURL: 'https://www.example.net/auth/example/callback'
* },
* function(token, tokenSecret, profile, done) {
* User.findOrCreate(..., function (err, user) {
* done(err, user);
* });
* }
* ));
*
* @param {Object} options
* @param {Function} verify
* @api public
*/
function OAuthStrategy(options, verify) {
options = options || {}
passport.Strategy.call(this);
this.name = 'oauth';
this._verify = verify;
if (!options.requestTokenURL) throw new Error('OAuthStrategy requires a requestTokenURL option');
if (!options.accessTokenURL) throw new Error('OAuthStrategy requires a accessTokenURL option');
if (!options.userAuthorizationURL) throw new Error('OAuthStrategy requires a userAuthorizationURL option');
if (!options.consumerKey) throw new Error('OAuthStrategy requires a consumerKey option');
if (!options.consumerSecret) throw new Error('OAuthStrategy requires a consumerSecret option');
if (!verify) throw new Error('OAuth authentication strategy requires a verify function');
// NOTE: The _oauth property is considered "protected". Subclasses are
// allowed to use it when making protected resource requests to retrieve
// the user profile.
this._oauth = new OAuth(options.requestTokenURL, options.accessTokenURL,
options.consumerKey, options.consumerSecret,
"1.0", options.callbackURL || null, "HMAC-SHA1");
this._userAuthorizationURL = options.userAuthorizationURL;
this._skipUserProfile = (options.skipUserProfile === undefined) ? false : options.skipUserProfile;
this._key = options.sessionKey || 'oauth';
}
/**
* Inherit from `passport.Strategy`.
*/
util.inherits(OAuthStrategy, passport.Strategy);
/**
* Authenticate request by delegating to a service provider using OAuth.
*
* @param {Object} req
* @api protected
*/
OAuthStrategy.prototype.authenticate = function(req, options) {
if (!req.session) { return this.error(new Error('OAuth authentication requires session support')); }
var self = this;
if (req.query && req.query['oauth_token']) {
// The request being authenticated contains an oauth_token parameter in the
// query portion of the URL. This indicates that the service provider has
// redirected the user back to the application, after authenticating the
// user and obtaining their authorization.
//
// The value of the oauth_token parameter is the request token. Together
// with knowledge of the token secret (stored in the session), the request
// token can be exchanged for an access token and token secret.
//
// This access token and token secret, along with the optional ability to
// fetch profile information from the service provider, is sufficient to
// establish the identity of the user.
// Bail if the session does not contain the request token and corresponding
// secret. If this happens, it is most likely caused by initiating OAuth
// from a different host than that of the callback endpoint (for example:
// initiating from 127.0.0.1 but handling callbacks at localhost).
if (!req.session[self._key]) { return self.error(new Error('failed to find request token in session')); }
var oauthToken = req.query['oauth_token'];
var oauthVerifier = req.query['oauth_verifier'] || null;
var oauthTokenSecret = req.session[self._key]["oauth_token_secret"];
// NOTE: The oauth_verifier parameter will be supplied in the query portion
// of the redirect URL, if the server supports OAuth 1.0a.
this._oauth.getOAuthAccessToken(oauthToken, oauthTokenSecret, oauthVerifier, function(err, token, tokenSecret, params) {
if (err) { return self.error(new InternalOAuthError('failed to obtain access token', err)); }
// The request token has been exchanged for an access token. Since the
// request token is a single-use token, that data can be removed from the
// session.
delete req.session[self._key]['oauth_token'];
delete req.session[self._key]['oauth_token_secret'];
if (Object.keys(req.session[self._key]).length == 0) {
delete req.session[self._key];
}
self._loadUserProfile(token, tokenSecret, params, function(err, profile) {
if (err) { return self.error(err); };
self._verify(token, tokenSecret, profile, function(err, user, info) {
if (err) { return self.error(err); }
if (!user) { return self.fail(info); }
self.success(user, info);
});
});
});
} else {
// In order to authenticate via OAuth, the application must obtain a request
// token from the service provider and redirect the user to the service
// provider to obtain their authorization. After authorization has been
// approved the user will be redirected back the application, at which point
// the application can exchange the request token for an access token.
//
// In order to successfully exchange the request token, its corresponding
// token secret needs to be known. The token secret will be temporarily
// stored in the session, so that it can be retrieved upon the user being
// redirected back to the application.
var params = this.requestTokenParams(options);
this._oauth.getOAuthRequestToken(params, function(err, token, tokenSecret, options) {
if (err) { return self.error(new InternalOAuthError('failed to obtain request token', err)); }
// NOTE: options will contain an oauth_callback_confirmed property set to
// true, if the server supports OAuth 1.0a.
// { oauth_callback_confirmed: 'true' }
if (!req.session[self._key]) { req.session[self._key] = {}; }
req.session[self._key]['oauth_token'] = token;
req.session[self._key]['oauth_token_secret'] = tokenSecret;
var parsed = url.parse(self._userAuthorizationURL, true);
parsed.query['oauth_token'] = token;
delete parsed.search;
var location = url.format(parsed);
self.redirect(location);
});
}
}
/**
* Retrieve user profile from service provider.
*
* OAuth-based authentication strategies can overrride this function in order to
* load the user's profile from the service provider. This assists applications
* (and users of those applications) in the initial registration process by
* automatically submitting required information.
*
* @param {String} accessToken
* @param {Function} done
* @api protected
*/
OAuthStrategy.prototype.userProfile = function(token, tokenSecret, params, done) {
return done(null, {});
}
/**
* Return extra parameters to be included in the request token request.
*
* Some OAuth providers require additional parameters to be included when
* issuing a request token. Since these parameters are not standardized by the
* OAuth specification, OAuth-based authentication strategies can overrride this
* function in order to populate these parameters as required by the provider.
*
* @param {Object} options
* @return {Object}
* @api protected
*/
OAuthStrategy.prototype.requestTokenParams = function(options) {
return {};
}
/**
* Load user profile, contingent upon options.
*
* @param {String} accessToken
* @param {Function} done
* @api private
*/
OAuthStrategy.prototype._loadUserProfile = function(token, tokenSecret, params, done) {
var self = this;
function loadIt() {
return self.userProfile(token, tokenSecret, params, done);
}
function skipIt() {
return done(null);
}
if (typeof this._skipUserProfile == 'function' && this._skipUserProfile.length > 1) {
// async
this._skipUserProfile(token, tokenSecret, function(err, skip) {
if (err) { return done(err); }
if (!skip) { return loadIt(); }
return skipIt();
});
} else {
var skip = (typeof this._skipUserProfile == 'function') ? this._skipUserProfile() : this._skipUserProfile;
if (!skip) { return loadIt(); }
return skipIt();
}
}
/**
* Expose `OAuthStrategy`.
*/
module.exports = OAuthStrategy;
jaredhanson-passport-oauth-e7afa47/lib/passport-oauth/strategies/oauth2.js 0000664 0000000 0000000 00000017660 11735720171 0027164 0 ustar 00root root 0000000 0000000 /**
* Module dependencies.
*/
var passport = require('passport')
, url = require('url')
, util = require('util')
, utils = require('./utils')
, OAuth2 = require('oauth').OAuth2
, InternalOAuthError = require('../errors/internaloautherror');
/**
* `OAuth2Strategy` constructor.
*
* The OAuth 2.0 authentication strategy authenticates requests using the OAuth
* 2.0 protocol.
*
* OAuth 2.0 provides a facility for delegated authentication, whereby users can
* authenticate using a third-party service such as Facebook. Delegating in
* this manner involves a sequence of events, including redirecting the user to
* the third-party service for authorization. Once authorization has been
* granted, the user is redirected back to the application and an authorization
* code can be used to obtain credentials.
*
* Applications must supply a `verify` callback which accepts an `accessToken`,
* `refreshToken` and service-specific `profile`, and then calls the `done`
* callback supplying a `user`, which should be set to `false` if the
* credentials are not valid. If an exception occured, `err` should be set.
*
* Options:
* - `authorizationURL` URL used to obtain an authorization grant
* - `tokenURL` URL used to obtain an access token
* - `clientID` identifies client to service provider
* - `clientSecret` secret used to establish ownership of the client identifer
* - `callbackURL` URL to which the service provider will redirect the user after obtaining authorization
*
* Examples:
*
* passport.use(new OAuth2Strategy({
* authorizationURL: 'https://www.example.com/oauth2/authorize',
* tokenURL: 'https://www.example.com/oauth2/token',
* clientID: '123-456-789',
* clientSecret: 'shhh-its-a-secret'
* callbackURL: 'https://www.example.net/auth/example/callback'
* },
* function(accessToken, refreshToken, profile, done) {
* User.findOrCreate(..., function (err, user) {
* done(err, user);
* });
* }
* ));
*
* @param {Object} options
* @param {Function} verify
* @api public
*/
function OAuth2Strategy(options, verify) {
options = options || {}
passport.Strategy.call(this);
this.name = 'oauth2';
this._verify = verify;
if (!options.authorizationURL) throw new Error('OAuth2Strategy requires a authorizationURL option');
if (!options.tokenURL) throw new Error('OAuthStrategy requires a tokenURL option');
if (!options.clientID) throw new Error('OAuth2Strategy requires a clientID option');
if (!options.clientSecret) throw new Error('OAuth2Strategy requires a clientSecret option');
// NOTE: The _oauth2 property is considered "protected". Subclasses are
// allowed to use it when making protected resource requests to retrieve
// the user profile.
this._oauth2 = new OAuth2(options.clientID, options.clientSecret,
'', options.authorizationURL, options.tokenURL);
this._callbackURL = options.callbackURL;
this._scopeSeparator = options.scopeSeparator || ' ';
this._skipUserProfile = (options.skipUserProfile === undefined) ? false : options.skipUserProfile;
}
/**
* Inherit from `passport.Strategy`.
*/
util.inherits(OAuth2Strategy, passport.Strategy);
/**
* Authenticate request by delegating to a service provider using OAuth 2.0.
*
* @param {Object} req
* @api protected
*/
OAuth2Strategy.prototype.authenticate = function(req, options) {
options = options || {};
var self = this;
if (req.query && req.query.error) {
// TODO: Error information pertaining to OAuth 2.0 flows is encoded in the
// query parameters, and should be propagated to the application.
return this.fail();
}
var callbackURL = options.callbackURL || this._callbackURL;
if (callbackURL) {
var parsed = url.parse(callbackURL);
if (!parsed.protocol) {
// The callback URL is relative, resolve a fully qualified URL from the
// URL of the originating request.
callbackURL = url.resolve(utils.originalURL(req), callbackURL);
}
}
if (req.query && req.query.code) {
var code = req.query.code;
// NOTE: The module oauth (0.9.5), which is a dependency, automatically adds
// a 'type=web_server' parameter to the percent-encoded data sent in
// the body of the access token request. This appears to be an
// artifact from an earlier draft of OAuth 2.0 (draft 22, as of the
// time of this writing). This parameter is not necessary, but its
// presence does not appear to cause any issues.
this._oauth2.getOAuthAccessToken(code, { grant_type: 'authorization_code', redirect_uri: callbackURL },
function(err, accessToken, refreshToken) {
if (err) { return self.error(new InternalOAuthError('failed to obtain access token', err)); }
self._loadUserProfile(accessToken, function(err, profile) {
if (err) { return self.error(err); };
self._verify(accessToken, refreshToken, profile, function(err, user, info) {
if (err) { return self.error(err); }
if (!user) { return self.fail(info); }
self.success(user, info);
});
});
}
);
} else {
// NOTE: The module oauth (0.9.5), which is a dependency, automatically adds
// a 'type=web_server' parameter to the query portion of the URL.
// This appears to be an artifact from an earlier draft of OAuth 2.0
// (draft 22, as of the time of this writing). This parameter is not
// necessary, but its presence does not appear to cause any issues.
var params = this.authorizationParams(options);
params['response_type'] = 'code';
params['redirect_uri'] = callbackURL;
var scope = options.scope;
if (scope) {
if (Array.isArray(scope)) { scope = scope.join(this._scopeSeparator); }
params.scope = scope;
}
var location = this._oauth2.getAuthorizeUrl(params);
this.redirect(location);
}
}
/**
* Retrieve user profile from service provider.
*
* OAuth 2.0-based authentication strategies can overrride this function in
* order to load the user's profile from the service provider. This assists
* applications (and users of those applications) in the initial registration
* process by automatically submitting required information.
*
* @param {String} accessToken
* @param {Function} done
* @api protected
*/
OAuth2Strategy.prototype.userProfile = function(accessToken, done) {
return done(null, {});
}
/**
* Return extra parameters to be included in the authorization request.
*
* Some OAuth 2.0 providers allow additional, non-standard parameters to be
* included when requesting authorization. Since these parameters are not
* standardized by the OAuth 2.0 specification, OAuth 2.0-based authentication
* strategies can overrride this function in order to populate these parameters
* as required by the provider.
*
* @param {Object} options
* @return {Object}
* @api protected
*/
OAuth2Strategy.prototype.authorizationParams = function(options) {
return {};
}
/**
* Load user profile, contingent upon options.
*
* @param {String} accessToken
* @param {Function} done
* @api private
*/
OAuth2Strategy.prototype._loadUserProfile = function(accessToken, done) {
var self = this;
function loadIt() {
return self.userProfile(accessToken, done);
}
function skipIt() {
return done(null);
}
if (typeof this._skipUserProfile == 'function' && this._skipUserProfile.length > 1) {
// async
this._skipUserProfile(accessToken, function(err, skip) {
if (err) { return done(err); }
if (!skip) { return loadIt(); }
return skipIt();
});
} else {
var skip = (typeof this._skipUserProfile == 'function') ? this._skipUserProfile() : this._skipUserProfile;
if (!skip) { return loadIt(); }
return skipIt();
}
}
/**
* Expose `OAuth2Strategy`.
*/
module.exports = OAuth2Strategy;
jaredhanson-passport-oauth-e7afa47/lib/passport-oauth/strategies/utils.js 0000664 0000000 0000000 00000001306 11735720171 0027110 0 ustar 00root root 0000000 0000000 /**
* Reconstructs the original URL of the request.
*
* This function builds a URL that corresponds the original URL requested by the
* client, including the protocol (http or https) and host.
*
* If the request passed through any proxies that terminate SSL, the
* `X-Forwarded-Proto` header is used to detect if the request was encrypted to
* the proxy.
*
* @return {String}
* @api private
*/
exports.originalURL = function(req) {
var headers = req.headers
, protocol = (req.connection.encrypted || req.headers['x-forwarded-proto'] == 'https')
? 'https'
: 'http'
, host = headers.host
, path = req.url || '';
return protocol + '://' + host + path;
};
jaredhanson-passport-oauth-e7afa47/package.json 0000664 0000000 0000000 00000001624 11735720171 0021772 0 ustar 00root root 0000000 0000000 {
"name": "passport-oauth",
"version": "0.1.7",
"description": "OAuth 1.0 and 2.0 authentication strategies for Passport.",
"author": { "name": "Jared Hanson", "email": "jaredhanson@gmail.com", "url": "http://www.jaredhanson.net/" },
"repository": {
"type": "git",
"url": "git://github.com/jaredhanson/passport-oauth.git"
},
"bugs": {
"url": "http://github.com/jaredhanson/passport-oauth/issues"
},
"main": "./lib/passport-oauth",
"dependencies": {
"pkginfo": "0.2.x",
"passport": "~0.1.1",
"oauth": "0.9.x"
},
"devDependencies": {
"vows": "0.6.x"
},
"scripts": {
"test": "NODE_PATH=lib node_modules/.bin/vows test/*-test.js test/**/*-test.js"
},
"engines": { "node": ">= 0.4.0" },
"licenses": [ {
"type": "MIT",
"url": "http://www.opensource.org/licenses/MIT"
} ],
"keywords": ["passport", "oauth", "auth", "authn", "authentication"]
}
jaredhanson-passport-oauth-e7afa47/test/ 0000775 0000000 0000000 00000000000 11735720171 0020460 5 ustar 00root root 0000000 0000000 jaredhanson-passport-oauth-e7afa47/test/errors/ 0000775 0000000 0000000 00000000000 11735720171 0021774 5 ustar 00root root 0000000 0000000 jaredhanson-passport-oauth-e7afa47/test/errors/internaloautherror-test.js 0000664 0000000 0000000 00000002202 11735720171 0027232 0 ustar 00root root 0000000 0000000 var vows = require('vows');
var assert = require('assert');
var util = require('util');
var InternalOAuthError = require('passport-oauth/errors/internaloautherror');
vows.describe('InternalOAuthError').addBatch({
'when constructed with only a message': {
topic: function() {
return new InternalOAuthError('oops');
},
'should format message properly': function (err) {
assert.equal(err.toString(), 'oops');
},
},
'when constructed with a message and error': {
topic: function() {
return new InternalOAuthError('oops', new Error('something is wrong'));
},
'should format message properly': function (err) {
assert.equal(err.toString(), 'oops (Error: something is wrong)');
},
},
'when constructed with a message and object with status code and data': {
topic: function() {
return new InternalOAuthError('oops', { statusCode: 401, data: 'invalid OAuth credentials' });
},
'should format message properly': function (err) {
assert.equal(err.toString(), 'oops (status: 401 data: invalid OAuth credentials)');
},
},
}).export(module);
jaredhanson-passport-oauth-e7afa47/test/index-test.js 0000664 0000000 0000000 00000000651 11735720171 0023104 0 ustar 00root root 0000000 0000000 var vows = require('vows');
var assert = require('assert');
var util = require('util');
var oauth = require('passport-oauth');
vows.describe('passport-oauth').addBatch({
'module': {
'should report a version': function (x) {
assert.isString(oauth.version);
},
'should export InternalOAuthError': function (x) {
assert.isFunction(oauth.InternalOAuthError);
},
},
}).export(module);
jaredhanson-passport-oauth-e7afa47/test/strategies/ 0000775 0000000 0000000 00000000000 11735720171 0022632 5 ustar 00root root 0000000 0000000 jaredhanson-passport-oauth-e7afa47/test/strategies/oauth-test.js 0000664 0000000 0000000 00000113250 11735720171 0025267 0 ustar 00root root 0000000 0000000 var vows = require('vows');
var assert = require('assert');
var util = require('util');
var OAuthStrategy = require('passport-oauth/strategies/oauth');
vows.describe('OAuthStrategy').addBatch({
'strategy': {
topic: function() {
return new OAuthStrategy({
requestTokenURL: 'https://www.example.com/oauth/request_token',
accessTokenURL: 'https://www.example.com/oauth/access_token',
userAuthorizationURL: 'https://www.example.com/oauth/authorize',
consumerKey: 'ABC123',
consumerSecret: 'secret'
},
function() {}
);
},
'should be named session': function (strategy) {
assert.equal(strategy.name, 'oauth');
},
},
'strategy handling an authorized request': {
topic: function() {
var strategy = new OAuthStrategy({
requestTokenURL: 'https://www.example.com/oauth/request_token',
accessTokenURL: 'https://www.example.com/oauth/access_token',
userAuthorizationURL: 'https://www.example.com/oauth/authorize',
consumerKey: 'ABC123',
consumerSecret: 'secret'
},
function(token, tokenSecret, profile, done) {
done(null, { token: token, tokenSecret: tokenSecret });
}
);
// mock
strategy._oauth.getOAuthAccessToken = function(token, tokenSecret, verifier, callback) {
callback(null, 'access-token', 'access-token-secret', {});
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
req.user = user;
self.callback(null, req);
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
req.query = {};
req.query['oauth_token'] = 'token';
req.session = {};
req.session['oauth'] = {};
req.session['oauth']['oauth_token'] = 'token';
req.session['oauth']['oauth_token_secret'] = 'token-secret';
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call fail' : function(err, req) {
assert.isNull(err);
},
'should authenticate' : function(err, req) {
assert.equal(req.user.token, 'access-token');
assert.equal(req.user.tokenSecret, 'access-token-secret');
},
'should remove token and token secret from session' : function(err, req) {
assert.isUndefined(req.session['oauth']);
},
},
},
'strategy handling an authorized request that is not verified': {
topic: function() {
var strategy = new OAuthStrategy({
requestTokenURL: 'https://www.example.com/oauth/request_token',
accessTokenURL: 'https://www.example.com/oauth/access_token',
userAuthorizationURL: 'https://www.example.com/oauth/authorize',
consumerKey: 'ABC123',
consumerSecret: 'secret'
},
function(token, tokenSecret, profile, done) {
done(null, false);
}
);
// mock
strategy._oauth.getOAuthAccessToken = function(token, tokenSecret, verifier, callback) {
callback(null, 'access-token', 'access-token-secret', {});
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(null, req);
}
req.query = {};
req.query['oauth_token'] = 'token';
req.session = {};
req.session['oauth'] = {};
req.session['oauth']['oauth_token'] = 'token';
req.session['oauth']['oauth_token_secret'] = 'token-secret';
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call success' : function(err, req) {
assert.isNull(err);
},
'should call fail' : function(err, req) {
assert.isNotNull(req);
},
'should remove token and token secret from session' : function(err, req) {
assert.isUndefined(req.session['oauth']);
},
},
},
'strategy handling an authorized request that is not verified with additional info': {
topic: function() {
var strategy = new OAuthStrategy({
requestTokenURL: 'https://www.example.com/oauth/request_token',
accessTokenURL: 'https://www.example.com/oauth/access_token',
userAuthorizationURL: 'https://www.example.com/oauth/authorize',
consumerKey: 'ABC123',
consumerSecret: 'secret'
},
function(token, tokenSecret, profile, done) {
done(null, false, { message: 'Invite required' });
}
);
// mock
strategy._oauth.getOAuthAccessToken = function(token, tokenSecret, verifier, callback) {
callback(null, 'access-token', 'access-token-secret', {});
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function(info) {
self.callback(null, req, info);
}
req.query = {};
req.query['oauth_token'] = 'token';
req.session = {};
req.session['oauth'] = {};
req.session['oauth']['oauth_token'] = 'token';
req.session['oauth']['oauth_token_secret'] = 'token-secret';
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call success' : function(err, req) {
assert.isNull(err);
},
'should call fail' : function(err, req) {
assert.isNotNull(req);
},
'should pass additional info' : function(err, req, info) {
assert.equal(info.message, 'Invite required');
},
'should remove token and token secret from session' : function(err, req) {
assert.isUndefined(req.session['oauth']);
},
},
},
'strategy handling an authorized request that encounters an error during verification': {
topic: function() {
var strategy = new OAuthStrategy({
requestTokenURL: 'https://www.example.com/oauth/request_token',
accessTokenURL: 'https://www.example.com/oauth/access_token',
userAuthorizationURL: 'https://www.example.com/oauth/authorize',
consumerKey: 'ABC123',
consumerSecret: 'secret'
},
function(token, tokenSecret, profile, done) {
done(new Error('something-went-wrong'));
}
);
// mock
strategy._oauth.getOAuthAccessToken = function(token, tokenSecret, verifier, callback) {
callback(null, 'access-token', 'access-token-secret', {});
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
strategy.error = function(err) {
self.callback(null, req);
}
req.query = {};
req.query['oauth_token'] = 'token';
req.session = {};
req.session['oauth'] = {};
req.session['oauth']['oauth_token'] = 'token';
req.session['oauth']['oauth_token_secret'] = 'token-secret';
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call success or fail' : function(err, req) {
assert.isNull(err);
},
'should call error' : function(err, req) {
assert.isNotNull(req);
},
'should remove token and token secret from session' : function(err, req) {
assert.isUndefined(req.session['oauth']);
},
},
},
'strategy handling an authorized request should load user profile by default': {
topic: function() {
var strategy = new OAuthStrategy({
requestTokenURL: 'https://www.example.com/oauth/request_token',
accessTokenURL: 'https://www.example.com/oauth/access_token',
userAuthorizationURL: 'https://www.example.com/oauth/authorize',
consumerKey: 'ABC123',
consumerSecret: 'secret'
},
function(token, tokenSecret, profile, done) {
done(null, { token: token, tokenSecret: tokenSecret }, profile);
}
);
// mock
strategy._oauth.getOAuthAccessToken = function(token, tokenSecret, verifier, callback) {
callback(null, 'access-token', 'access-token-secret', {});
}
strategy.userProfile = function(token, tokenSecret, params, done) {
done(null, { username: 'jaredhanson', location: 'Oakland, CA' });
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user, info) {
req.user = user;
self.callback(null, req, info);
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
req.query = {};
req.query['oauth_token'] = 'token';
req.session = {};
req.session['oauth'] = {};
req.session['oauth']['oauth_token'] = 'token';
req.session['oauth']['oauth_token_secret'] = 'token-secret';
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call fail' : function(err, req) {
assert.isNull(err);
},
'should authenticate' : function(err, req) {
assert.equal(req.user.token, 'access-token');
assert.equal(req.user.tokenSecret, 'access-token-secret');
},
'should provide profile' : function(err, req, profile) {
assert.equal(profile.location, 'Oakland, CA');
},
'should remove token and token secret from session' : function(err, req) {
assert.isUndefined(req.session['oauth']);
},
},
},
'strategy handling an authorized request should not load user profile when option is disabled': {
topic: function() {
var strategy = new OAuthStrategy({
requestTokenURL: 'https://www.example.com/oauth/request_token',
accessTokenURL: 'https://www.example.com/oauth/access_token',
userAuthorizationURL: 'https://www.example.com/oauth/authorize',
consumerKey: 'ABC123',
consumerSecret: 'secret',
skipUserProfile: true
},
function(token, tokenSecret, profile, done) {
done(null, { token: token, tokenSecret: tokenSecret }, profile);
}
);
// mock
strategy._oauth.getOAuthAccessToken = function(token, tokenSecret, verifier, callback) {
callback(null, 'access-token', 'access-token-secret', {});
}
strategy.userProfile = function(token, tokenSecret, params, done) {
done(null, { username: 'jaredhanson', location: 'Oakland, CA' });
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user, info) {
req.user = user;
self.callback(null, req, info);
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
req.query = {};
req.query['oauth_token'] = 'token';
req.session = {};
req.session['oauth'] = {};
req.session['oauth']['oauth_token'] = 'token';
req.session['oauth']['oauth_token_secret'] = 'token-secret';
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call fail' : function(err, req) {
assert.isNull(err);
},
'should authenticate' : function(err, req) {
assert.equal(req.user.token, 'access-token');
assert.equal(req.user.tokenSecret, 'access-token-secret');
},
'should not provide profile' : function(err, req, profile) {
assert.isUndefined(profile);
},
'should remove token and token secret from session' : function(err, req) {
assert.isUndefined(req.session['oauth']);
},
},
},
'strategy handling an authorized request should load user profile when function synchronously returns false': {
topic: function() {
var strategy = new OAuthStrategy({
requestTokenURL: 'https://www.example.com/oauth/request_token',
accessTokenURL: 'https://www.example.com/oauth/access_token',
userAuthorizationURL: 'https://www.example.com/oauth/authorize',
consumerKey: 'ABC123',
consumerSecret: 'secret',
skipUserProfile: function() {
return false;
}
},
function(token, tokenSecret, profile, done) {
done(null, { token: token, tokenSecret: tokenSecret }, profile);
}
);
// mock
strategy._oauth.getOAuthAccessToken = function(token, tokenSecret, verifier, callback) {
callback(null, 'access-token', 'access-token-secret', {});
}
strategy.userProfile = function(token, tokenSecret, params, done) {
done(null, { username: 'jaredhanson', location: 'Oakland, CA' });
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user, info) {
req.user = user;
self.callback(null, req, info);
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
req.query = {};
req.query['oauth_token'] = 'token';
req.session = {};
req.session['oauth'] = {};
req.session['oauth']['oauth_token'] = 'token';
req.session['oauth']['oauth_token_secret'] = 'token-secret';
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call fail' : function(err, req) {
assert.isNull(err);
},
'should authenticate' : function(err, req) {
assert.equal(req.user.token, 'access-token');
assert.equal(req.user.tokenSecret, 'access-token-secret');
},
'should provide profile' : function(err, req, profile) {
assert.equal(profile.location, 'Oakland, CA');
},
'should remove token and token secret from session' : function(err, req) {
assert.isUndefined(req.session['oauth']);
},
},
},
'strategy handling an authorized request should not load user profile when function synchronously returns true': {
topic: function() {
var strategy = new OAuthStrategy({
requestTokenURL: 'https://www.example.com/oauth/request_token',
accessTokenURL: 'https://www.example.com/oauth/access_token',
userAuthorizationURL: 'https://www.example.com/oauth/authorize',
consumerKey: 'ABC123',
consumerSecret: 'secret',
skipUserProfile: function() {
return true;
}
},
function(token, tokenSecret, profile, done) {
done(null, { token: token, tokenSecret: tokenSecret }, profile);
}
);
// mock
strategy._oauth.getOAuthAccessToken = function(token, tokenSecret, verifier, callback) {
callback(null, 'access-token', 'access-token-secret', {});
}
strategy.userProfile = function(token, tokenSecret, params, done) {
done(null, { username: 'jaredhanson', location: 'Oakland, CA' });
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user, info) {
req.user = user;
self.callback(null, req, info);
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
req.query = {};
req.query['oauth_token'] = 'token';
req.session = {};
req.session['oauth'] = {};
req.session['oauth']['oauth_token'] = 'token';
req.session['oauth']['oauth_token_secret'] = 'token-secret';
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call fail' : function(err, req) {
assert.isNull(err);
},
'should authenticate' : function(err, req) {
assert.equal(req.user.token, 'access-token');
assert.equal(req.user.tokenSecret, 'access-token-secret');
},
'should not provide profile' : function(err, req, profile) {
assert.isUndefined(profile);
},
'should remove token and token secret from session' : function(err, req) {
assert.isUndefined(req.session['oauth']);
},
},
},
'strategy handling an authorized request should load user profile when function asynchronously returns false': {
topic: function() {
var strategy = new OAuthStrategy({
requestTokenURL: 'https://www.example.com/oauth/request_token',
accessTokenURL: 'https://www.example.com/oauth/access_token',
userAuthorizationURL: 'https://www.example.com/oauth/authorize',
consumerKey: 'ABC123',
consumerSecret: 'secret',
skipUserProfile: function(token, tokenSecret, done) {
done(null, false);
}
},
function(token, tokenSecret, profile, done) {
done(null, { token: token, tokenSecret: tokenSecret }, profile);
}
);
// mock
strategy._oauth.getOAuthAccessToken = function(token, tokenSecret, verifier, callback) {
callback(null, 'access-token', 'access-token-secret', {});
}
strategy.userProfile = function(token, tokenSecret, params, done) {
done(null, { username: 'jaredhanson', location: 'Oakland, CA' });
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user, info) {
req.user = user;
self.callback(null, req, info);
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
req.query = {};
req.query['oauth_token'] = 'token';
req.session = {};
req.session['oauth'] = {};
req.session['oauth']['oauth_token'] = 'token';
req.session['oauth']['oauth_token_secret'] = 'token-secret';
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call fail' : function(err, req) {
assert.isNull(err);
},
'should authenticate' : function(err, req) {
assert.equal(req.user.token, 'access-token');
assert.equal(req.user.tokenSecret, 'access-token-secret');
},
'should provide profile' : function(err, req, profile) {
assert.equal(profile.location, 'Oakland, CA');
},
'should remove token and token secret from session' : function(err, req) {
assert.isUndefined(req.session['oauth']);
},
},
},
'strategy handling an authorized request should load user profile when function asynchronously returns true': {
topic: function() {
var strategy = new OAuthStrategy({
requestTokenURL: 'https://www.example.com/oauth/request_token',
accessTokenURL: 'https://www.example.com/oauth/access_token',
userAuthorizationURL: 'https://www.example.com/oauth/authorize',
consumerKey: 'ABC123',
consumerSecret: 'secret',
skipUserProfile: function(token, tokenSecret, done) {
done(null, true);
}
},
function(token, tokenSecret, profile, done) {
done(null, { token: token, tokenSecret: tokenSecret }, profile);
}
);
// mock
strategy._oauth.getOAuthAccessToken = function(token, tokenSecret, verifier, callback) {
callback(null, 'access-token', 'access-token-secret', {});
}
strategy.userProfile = function(token, tokenSecret, params, done) {
done(null, { username: 'jaredhanson', location: 'Oakland, CA' });
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user, info) {
req.user = user;
self.callback(null, req, info);
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
req.query = {};
req.query['oauth_token'] = 'token';
req.session = {};
req.session['oauth'] = {};
req.session['oauth']['oauth_token'] = 'token';
req.session['oauth']['oauth_token_secret'] = 'token-secret';
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call fail' : function(err, req) {
assert.isNull(err);
},
'should authenticate' : function(err, req) {
assert.equal(req.user.token, 'access-token');
assert.equal(req.user.tokenSecret, 'access-token-secret');
},
'should not provide profile' : function(err, req, profile) {
assert.isUndefined(profile);
},
'should remove token and token secret from session' : function(err, req) {
assert.isUndefined(req.session['oauth']);
},
},
},
'strategy handling an authorized request that fails to load user profile': {
topic: function() {
var strategy = new OAuthStrategy({
requestTokenURL: 'https://www.example.com/oauth/request_token',
accessTokenURL: 'https://www.example.com/oauth/access_token',
userAuthorizationURL: 'https://www.example.com/oauth/authorize',
consumerKey: 'ABC123',
consumerSecret: 'secret'
},
function(token, tokenSecret, profile, done) {
done(null, { token: token, tokenSecret: tokenSecret }, profile);
}
);
// mock
strategy._oauth.getOAuthAccessToken = function(token, tokenSecret, verifier, callback) {
callback(null, 'access-token', 'access-token-secret', {});
}
strategy.userProfile = function(token, tokenSecret, params, done) {
done(new Error('something-went-wrong'));
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user, info) {
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
strategy.error = function(err) {
self.callback(null, req);
}
req.query = {};
req.query['oauth_token'] = 'token';
req.session = {};
req.session['oauth'] = {};
req.session['oauth']['oauth_token'] = 'token';
req.session['oauth']['oauth_token_secret'] = 'token-secret';
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call success or fail' : function(err, req) {
assert.isNull(err);
},
'should call error' : function(err, req) {
assert.isNotNull(req);
},
'should remove token and token secret from session' : function(err, req) {
assert.isUndefined(req.session['oauth']);
},
},
},
'strategy handling an authorized request that fails to obtain an access token': {
topic: function() {
var strategy = new OAuthStrategy({
requestTokenURL: 'https://www.example.com/oauth/request_token',
accessTokenURL: 'https://www.example.com/oauth/access_token',
userAuthorizationURL: 'https://www.example.com/oauth/authorize',
consumerKey: 'ABC123',
consumerSecret: 'secret'
},
function() {}
);
// mock
strategy._oauth.getOAuthAccessToken = function(token, tokenSecret, verifier, callback) {
callback(new Error('something-went-wrong'));
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
strategy.error = function(err) {
self.callback(null, req);
}
req.query = {};
req.query['oauth_token'] = 'token';
req.session = {};
req.session['oauth'] = {};
req.session['oauth']['oauth_token'] = 'token';
req.session['oauth']['oauth_token_secret'] = 'token-secret';
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call success or fail' : function(err, req) {
assert.isNull(err);
},
'should call error' : function(err, req) {
assert.isNotNull(req);
},
'should not remove token and token secret from session' : function(err, req) {
assert.equal(req.session['oauth']['oauth_token'], 'token');
assert.equal(req.session['oauth']['oauth_token_secret'], 'token-secret');
},
},
},
'strategy handling an authorized request that lacks request token in session': {
topic: function() {
var strategy = new OAuthStrategy({
requestTokenURL: 'https://www.example.com/oauth/request_token',
accessTokenURL: 'https://www.example.com/oauth/access_token',
userAuthorizationURL: 'https://www.example.com/oauth/authorize',
consumerKey: 'ABC123',
consumerSecret: 'secret'
},
function(token, tokenSecret, profile, done) {
done(null, { token: token, tokenSecret: tokenSecret });
}
);
// mock
strategy._oauth.getOAuthAccessToken = function(token, tokenSecret, verifier, callback) {
callback(null, 'access-token', 'access-token-secret', {});
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
req.user = user;
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
strategy.error = function(err) {
self.callback(null, req, err);
}
req.query = {};
req.query['oauth_token'] = 'token';
req.session = {};
//req.session['oauth'] = {};
//req.session['oauth']['oauth_token'] = 'token';
//req.session['oauth']['oauth_token_secret'] = 'token-secret';
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call success or fail' : function(err, req) {
assert.isNull(err);
},
'should call error' : function(err, req, e) {
assert.isNotNull(req);
assert.instanceOf(e, Error);
},
},
},
'strategy handling a request to be redirected after obtaining a request token': {
topic: function() {
var strategy = new OAuthStrategy({
requestTokenURL: 'https://www.example.com/oauth/request_token',
accessTokenURL: 'https://www.example.com/oauth/access_token',
userAuthorizationURL: 'https://www.example.com/oauth/authorize',
consumerKey: 'ABC123',
consumerSecret: 'secret'
},
function() {}
);
// mock
strategy._oauth.getOAuthRequestToken = function(extraParams, callback) {
callback(null, 'token', 'token-secret', {});
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
strategy.redirect = function(url) {
req.redirectURL = url;
self.callback(null, req);
}
req.session = {};
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call success or fail' : function(err, req) {
assert.isNull(err);
},
'should redirect to user authorization URL' : function(err, req) {
assert.equal(req.redirectURL, 'https://www.example.com/oauth/authorize?oauth_token=token');
},
'should store token and token secret in session' : function(err, req) {
assert.equal(req.session['oauth']['oauth_token'], 'token');
assert.equal(req.session['oauth']['oauth_token_secret'], 'token-secret');
},
},
},
'strategy handling a request to be redirected to a URL with query parameters after obtaining a request token': {
topic: function() {
var strategy = new OAuthStrategy({
requestTokenURL: 'https://www.example.com/oauth/request_token',
accessTokenURL: 'https://www.example.com/oauth/access_token',
userAuthorizationURL: 'https://www.example.com/oauth/authorize?foo=bar',
consumerKey: 'ABC123',
consumerSecret: 'secret'
},
function() {}
);
// mock
strategy._oauth.getOAuthRequestToken = function(extraParams, callback) {
callback(null, 'token', 'token-secret', {});
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
strategy.redirect = function(url) {
req.redirectURL = url;
self.callback(null, req);
}
req.session = {};
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call success or fail' : function(err, req) {
assert.isNull(err);
},
'should redirect to user authorization URL' : function(err, req) {
assert.equal(req.redirectURL, 'https://www.example.com/oauth/authorize?foo=bar&oauth_token=token');
},
'should store token and token secret in session' : function(err, req) {
assert.equal(req.session['oauth']['oauth_token'], 'token');
assert.equal(req.session['oauth']['oauth_token_secret'], 'token-secret');
},
},
},
'strategy handling a request to be redirected after obtaining a request token without extra params': {
topic: function() {
var strategy = new OAuthStrategy({
requestTokenURL: 'https://www.example.com/oauth/request_token',
accessTokenURL: 'https://www.example.com/oauth/access_token',
userAuthorizationURL: 'https://www.example.com/oauth/authorize',
consumerKey: 'ABC123',
consumerSecret: 'secret'
},
function() {}
);
// mock
strategy._oauth.getOAuthRequestToken = function(extraParams, callback) {
if (Object.keys(extraParams).length == 0) {
callback(null, 'token', 'token-secret', {});
} else {
callback(new Error('something went wrong'));
}
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
strategy.redirect = function(url) {
req.redirectURL = url;
self.callback(null, req);
}
strategy.error = function(err) {
self.callback(err);
}
req.session = {};
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call success or fail' : function(err, req) {
assert.isNull(err);
},
'should redirect to user authorization URL' : function(err, req) {
assert.equal(req.redirectURL, 'https://www.example.com/oauth/authorize?oauth_token=token');
},
'should store token and token secret in session' : function(err, req) {
assert.equal(req.session['oauth']['oauth_token'], 'token');
assert.equal(req.session['oauth']['oauth_token_secret'], 'token-secret');
},
},
},
'strategy handling a request to be redirected after obtaining a request token with extra params': {
topic: function() {
var strategy = new OAuthStrategy({
requestTokenURL: 'https://www.example.com/oauth/request_token',
accessTokenURL: 'https://www.example.com/oauth/access_token',
userAuthorizationURL: 'https://www.example.com/oauth/authorize',
consumerKey: 'ABC123',
consumerSecret: 'secret'
},
function() {}
);
// mock
strategy._oauth.getOAuthRequestToken = function(extraParams, callback) {
if (Object.keys(extraParams).length == 1) {
callback(null, 'token_' + extraParams.scope, 'token-secret', {});
} else {
callback(new Error('something went wrong'));
}
}
strategy.requestTokenParams = function(options) {
return { scope: options.scope };
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
strategy.redirect = function(url) {
req.redirectURL = url;
self.callback(null, req);
}
strategy.error = function(err) {
self.callback(err);
}
req.session = {};
process.nextTick(function () {
strategy.authenticate(req, { scope: 'foo' });
});
},
'should not call success or fail' : function(err, req) {
assert.isNull(err);
},
'should redirect to user authorization URL' : function(err, req) {
assert.equal(req.redirectURL, 'https://www.example.com/oauth/authorize?oauth_token=token_foo');
},
'should store token and token secret in session' : function(err, req) {
assert.equal(req.session['oauth']['oauth_token'], 'token_foo');
assert.equal(req.session['oauth']['oauth_token_secret'], 'token-secret');
},
},
},
'strategy handling a request that fails to obtain a request token': {
topic: function() {
var strategy = new OAuthStrategy({
requestTokenURL: 'https://www.example.com/oauth/request_token',
accessTokenURL: 'https://www.example.com/oauth/access_token',
userAuthorizationURL: 'https://www.example.com/oauth/authorize',
consumerKey: 'ABC123',
consumerSecret: 'secret'
},
function() {}
);
// mock
strategy._oauth.getOAuthRequestToken = function(extraParams, callback) {
callback(new Error('something-went-wrong'));
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
strategy.redirect = function(url) {
self.callback(new Error('should-not-be-called'));
}
strategy.error = function(err) {
self.callback(null, req);
}
req.session = {};
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call success or fail or redirect' : function(err, req) {
assert.isNull(err);
},
'should call error' : function(err, req) {
assert.isNotNull(req);
},
'should not store token and token secret in session' : function(err, req) {
assert.isUndefined(req.session['oauth']);
},
},
},
'strategy constructed without a verify callback': {
'should throw an error': function (strategy) {
assert.throws(function() {
new OAuthStrategy({
requestTokenURL: 'https://www.example.com/oauth/request_token',
accessTokenURL: 'https://www.example.com/oauth/access_token',
userAuthorizationURL: 'https://www.example.com/oauth/authorize',
consumerKey: 'ABC123',
consumerSecret: 'secret'
});
});
},
},
}).export(module);
jaredhanson-passport-oauth-e7afa47/test/strategies/oauth2-test.js 0000664 0000000 0000000 00000127435 11735720171 0025363 0 ustar 00root root 0000000 0000000 var vows = require('vows');
var assert = require('assert');
var util = require('util');
var OAuth2Strategy = require('passport-oauth/strategies/oauth2');
vows.describe('OAuth2Strategy').addBatch({
'strategy': {
topic: function() {
return new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret'
},
function() {}
);
},
'should be named session': function (strategy) {
assert.equal(strategy.name, 'oauth2');
},
},
'strategy handling an authorized request': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret',
callbackURL: 'https://www.example.net/auth/example/callback',
},
function(accessToken, refreshToken, profile, done) {
done(null, { accessToken: accessToken, refreshToken: refreshToken });
}
);
// mock
strategy._oauth2.getOAuthAccessToken = function(code, options, callback) {
if (options.redirect_uri == 'https://www.example.net/auth/example/callback') {
callback(null, 'token', 'refresh-token');
} else {
callback(null, 'bad', 'really-bad');
}
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
req.user = user;
self.callback(null, req);
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
req.query = {};
req.query.code = 'authorization-code'
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call fail' : function(err, req) {
assert.isNull(err);
},
'should authenticate' : function(err, req) {
assert.equal(req.user.accessToken, 'token');
assert.equal(req.user.refreshToken, 'refresh-token');
},
},
},
'strategy handling an authorized request with a callbackURL option override': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret',
callbackURL: 'https://www.example.net/auth/example/callback',
},
function(accessToken, refreshToken, profile, done) {
done(null, { accessToken: accessToken, refreshToken: refreshToken });
}
);
// mock
strategy._oauth2.getOAuthAccessToken = function(code, options, callback) {
if (options.redirect_uri == 'https://www.example.net/auth/example/other-callback') {
callback(null, 'token', 'refresh-token');
} else {
callback(null, 'bad', 'really-bad');
}
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
req.user = user;
self.callback(null, req);
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
req.query = {};
req.query.code = 'authorization-code'
process.nextTick(function () {
strategy.authenticate(req, { callbackURL: 'https://www.example.net/auth/example/other-callback' });
});
},
'should not call fail' : function(err, req) {
assert.isNull(err);
},
'should authenticate' : function(err, req) {
assert.equal(req.user.accessToken, 'token');
assert.equal(req.user.refreshToken, 'refresh-token');
},
},
},
'strategy handling an authorized request with a relative callbackURL option override': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret',
callbackURL: 'https://www.example.net/auth/example/callback',
},
function(accessToken, refreshToken, profile, done) {
done(null, { accessToken: accessToken, refreshToken: refreshToken });
}
);
// mock
strategy._oauth2.getOAuthAccessToken = function(code, options, callback) {
if (options.redirect_uri == 'https://www.example.net/auth/example/another-callback') {
callback(null, 'token', 'refresh-token');
} else {
callback(null, 'bad', 'really-bad');
}
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {
connection: { encrypted: true },
url: '/auth/example',
headers: {
'host': 'www.example.net',
}
};
strategy.success = function(user) {
req.user = user;
self.callback(null, req);
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
req.query = {};
req.query.code = 'authorization-code'
process.nextTick(function () {
strategy.authenticate(req, { callbackURL: '/auth/example/another-callback' });
});
},
'should not call fail' : function(err, req) {
assert.isNull(err);
},
'should authenticate' : function(err, req) {
assert.equal(req.user.accessToken, 'token');
assert.equal(req.user.refreshToken, 'refresh-token');
},
},
},
'strategy handling an authorized request that is not verified': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret'
},
function(accessToken, refreshToken, profile, done) {
done(null, false);
}
);
// mock
strategy._oauth2.getOAuthAccessToken = function(code, options, callback) {
callback(null, 'token', 'refresh-token');
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
req.user = user;
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(null, req);
}
req.query = {};
req.query.code = 'authorization-code'
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call success' : function(err, req) {
assert.isNull(err);
},
'should call fail' : function(err, req) {
assert.isNotNull(req);
},
},
},
'strategy handling an authorized request that is not verified with additional info': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret'
},
function(accessToken, refreshToken, profile, done) {
done(null, false, { message: 'Invite required' });
}
);
// mock
strategy._oauth2.getOAuthAccessToken = function(code, options, callback) {
callback(null, 'token', 'refresh-token');
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
req.user = user;
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function(info) {
self.callback(null, req, info);
}
req.query = {};
req.query.code = 'authorization-code'
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call success' : function(err, req) {
assert.isNull(err);
},
'should call fail' : function(err, req) {
assert.isNotNull(req);
},
'should pass additional info' : function(err, req, info) {
assert.equal(info.message, 'Invite required');
},
},
},
'strategy handling an authorized request that encounters an error during verification': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret'
},
function(accessToken, refreshToken, profile, done) {
done(new Error('something-went-wrong'));
}
);
// mock
strategy._oauth2.getOAuthAccessToken = function(code, options, callback) {
callback(null, 'token', 'refresh-token');
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
req.user = user;
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
strategy.error = function(err) {
self.callback(null, req);
}
req.query = {};
req.query.code = 'authorization-code'
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call success or fail' : function(err, req) {
assert.isNull(err);
},
'should call error' : function(err, req) {
assert.isNotNull(req);
},
},
},
'strategy handling an authorized request should load user profile by default': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret'
},
function(accessToken, refreshToken, profile, done) {
done(null, { accessToken: accessToken, refreshToken: refreshToken }, profile);
}
);
// mock
strategy._oauth2.getOAuthAccessToken = function(code, options, callback) {
callback(null, 'token', 'refresh-token');
}
strategy.userProfile = function(accessToken, done) {
done(null, { username: 'jaredhanson', location: 'Oakland, CA' });
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user, info) {
req.user = user;
self.callback(null, req, info);
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
req.query = {};
req.query.code = 'authorization-code'
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call fail' : function(err, req) {
assert.isNull(err);
},
'should authenticate' : function(err, req) {
assert.equal(req.user.accessToken, 'token');
assert.equal(req.user.refreshToken, 'refresh-token');
},
'should provide profile' : function(err, req, profile) {
assert.equal(profile.location, 'Oakland, CA');
},
},
},
'strategy handling an authorized request should not load user profile when option is disabled': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret',
skipUserProfile: true
},
function(accessToken, refreshToken, profile, done) {
done(null, { accessToken: accessToken, refreshToken: refreshToken }, profile);
}
);
// mock
strategy._oauth2.getOAuthAccessToken = function(code, options, callback) {
callback(null, 'token', 'refresh-token');
}
strategy.userProfile = function(accessToken, done) {
done(null, { username: 'jaredhanson', location: 'Oakland, CA' });
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user, info) {
req.user = user;
self.callback(null, req, info);
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
req.query = {};
req.query.code = 'authorization-code'
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call fail' : function(err, req) {
assert.isNull(err);
},
'should authenticate' : function(err, req) {
assert.equal(req.user.accessToken, 'token');
assert.equal(req.user.refreshToken, 'refresh-token');
},
'should not provide profile' : function(err, req, profile) {
assert.isUndefined(profile);
},
},
},
'strategy handling an authorized request should load user profile when function synchronously returns false': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret',
skipUserProfile: function() {
return false;
}
},
function(accessToken, refreshToken, profile, done) {
done(null, { accessToken: accessToken, refreshToken: refreshToken }, profile);
}
);
// mock
strategy._oauth2.getOAuthAccessToken = function(code, options, callback) {
callback(null, 'token', 'refresh-token');
}
strategy.userProfile = function(accessToken, done) {
done(null, { username: 'jaredhanson', location: 'Oakland, CA' });
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user, info) {
req.user = user;
self.callback(null, req, info);
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
req.query = {};
req.query.code = 'authorization-code'
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call fail' : function(err, req) {
assert.isNull(err);
},
'should authenticate' : function(err, req) {
assert.equal(req.user.accessToken, 'token');
assert.equal(req.user.refreshToken, 'refresh-token');
},
'should provide profile' : function(err, req, profile) {
assert.equal(profile.location, 'Oakland, CA');
},
},
},
'strategy handling an authorized request should not load user profile when function synchronously returns true': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret',
skipUserProfile: function() {
return true;
}
},
function(accessToken, refreshToken, profile, done) {
done(null, { accessToken: accessToken, refreshToken: refreshToken }, profile);
}
);
// mock
strategy._oauth2.getOAuthAccessToken = function(code, options, callback) {
callback(null, 'token', 'refresh-token');
}
strategy.userProfile = function(accessToken, done) {
done(null, { username: 'jaredhanson', location: 'Oakland, CA' });
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user, info) {
req.user = user;
self.callback(null, req, info);
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
req.query = {};
req.query.code = 'authorization-code'
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call fail' : function(err, req) {
assert.isNull(err);
},
'should authenticate' : function(err, req) {
assert.equal(req.user.accessToken, 'token');
assert.equal(req.user.refreshToken, 'refresh-token');
},
'should not provide profile' : function(err, req, profile) {
assert.isUndefined(profile);
},
},
},
'strategy handling an authorized request should load user profile when function asynchronously returns false': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret',
skipUserProfile: function(accessToken, done) {
done(null, false);
}
},
function(accessToken, refreshToken, profile, done) {
done(null, { accessToken: accessToken, refreshToken: refreshToken }, profile);
}
);
// mock
strategy._oauth2.getOAuthAccessToken = function(code, options, callback) {
callback(null, 'token', 'refresh-token');
}
strategy.userProfile = function(accessToken, done) {
done(null, { username: 'jaredhanson', location: 'Oakland, CA' });
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user, info) {
req.user = user;
self.callback(null, req, info);
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
req.query = {};
req.query.code = 'authorization-code'
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call fail' : function(err, req) {
assert.isNull(err);
},
'should authenticate' : function(err, req) {
assert.equal(req.user.accessToken, 'token');
assert.equal(req.user.refreshToken, 'refresh-token');
},
'should provide profile' : function(err, req, profile) {
assert.equal(profile.location, 'Oakland, CA');
},
},
},
'strategy handling an authorized request should not load user profile when function asynchronously returns true': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret',
skipUserProfile: function(accessToken, done) {
done(null, true);
}
},
function(accessToken, refreshToken, profile, done) {
done(null, { accessToken: accessToken, refreshToken: refreshToken }, profile);
}
);
// mock
strategy._oauth2.getOAuthAccessToken = function(code, options, callback) {
callback(null, 'token', 'refresh-token');
}
strategy.userProfile = function(accessToken, done) {
done(null, { username: 'jaredhanson', location: 'Oakland, CA' });
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user, info) {
req.user = user;
self.callback(null, req, info);
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
req.query = {};
req.query.code = 'authorization-code'
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call fail' : function(err, req) {
assert.isNull(err);
},
'should authenticate' : function(err, req) {
assert.equal(req.user.accessToken, 'token');
assert.equal(req.user.refreshToken, 'refresh-token');
},
'should not provide profile' : function(err, req, profile) {
assert.isUndefined(profile);
},
},
},
'strategy handling an authorized request that fails to load user profile': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret'
},
function(accessToken, refreshToken, profile, done) {
done(null, { accessToken: accessToken, refreshToken: refreshToken }, profile);
}
);
// mock
strategy._oauth2.getOAuthAccessToken = function(code, options, callback) {
callback(null, 'token', 'refresh-token');
}
strategy.userProfile = function(accessToken, done) {
done(new Error('something-went-wrong'));
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user, info) {
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
strategy.error = function(err) {
self.callback(null, req);
}
req.query = {};
req.query.code = 'authorization-code'
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call success or fail' : function(err, req) {
assert.isNull(err);
},
'should call error' : function(err, req) {
assert.isNotNull(req);
},
},
},
'strategy handling an authorized request that fails to obtain an access token': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret'
},
function(accessToken, refreshToken, profile, done) {}
);
// mock
strategy._oauth2.getOAuthAccessToken = function(code, options, callback) {
callback(new Error('something-went-wrong'));
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
req.user = user;
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
strategy.error = function(err) {
self.callback(null, req);
}
req.query = {};
req.query.code = 'authorization-code'
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call success or fail' : function(err, req) {
assert.isNull(err);
},
'should call error' : function(err, req) {
assert.isNotNull(req);
},
},
},
'strategy handling a request to be redirected for authorization': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret',
callbackURL: 'https://www.example.net/auth/example/callback'
},
function(accessToken, refreshToken, profile, done) {}
);
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
req.user = user;
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
strategy.redirect = function(url) {
req.redirectURL = url;
self.callback(null, req);
}
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call success or fail' : function(err, req) {
assert.isNull(err);
},
'should redirect to user authorization URL' : function(err, req) {
assert.equal(req.redirectURL, 'https://www.example.com/oauth2/authorize?response_type=code&redirect_uri=https%3A%2F%2Fwww.example.net%2Fauth%2Fexample%2Fcallback&client_id=ABC123&type=web_server');
},
},
},
'strategy handling a request to be redirected to a path for authorization': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret',
callbackURL: '/auth/example/callback'
},
function(accessToken, refreshToken, profile, done) {}
);
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {
connection: {},
url: '/auth/example',
headers: {
'host': 'www.example.net',
}
};
strategy.success = function(user) {
req.user = user;
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
strategy.redirect = function(url) {
req.redirectURL = url;
self.callback(null, req);
}
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call success or fail' : function(err, req) {
assert.isNull(err);
},
'should redirect to user authorization URL' : function(err, req) {
assert.equal(req.redirectURL, 'https://www.example.com/oauth2/authorize?response_type=code&redirect_uri=http%3A%2F%2Fwww.example.net%2Fauth%2Fexample%2Fcallback&client_id=ABC123&type=web_server');
},
},
},
'strategy handling an encrypted request to be redirected to a path for authorization': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret',
callbackURL: '/auth/example/callback'
},
function(accessToken, refreshToken, profile, done) {}
);
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {
connection: { encrypted: true },
url: '/auth/example',
headers: {
'host': 'www.example.net',
}
};
strategy.success = function(user) {
req.user = user;
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
strategy.redirect = function(url) {
req.redirectURL = url;
self.callback(null, req);
}
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call success or fail' : function(err, req) {
assert.isNull(err);
},
'should redirect to user authorization URL' : function(err, req) {
assert.equal(req.redirectURL, 'https://www.example.com/oauth2/authorize?response_type=code&redirect_uri=https%3A%2F%2Fwww.example.net%2Fauth%2Fexample%2Fcallback&client_id=ABC123&type=web_server');
},
},
},
'strategy handling an encrypted request from behind a proxy to be redirected to a path for authorization': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret',
callbackURL: '/auth/example/callback'
},
function(accessToken, refreshToken, profile, done) {}
);
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {
connection: {},
url: '/auth/example',
headers: {
'host': 'www.example.net',
'x-forwarded-proto': 'https'
}
};
strategy.success = function(user) {
req.user = user;
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
strategy.redirect = function(url) {
req.redirectURL = url;
self.callback(null, req);
}
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call success or fail' : function(err, req) {
assert.isNull(err);
},
'should redirect to user authorization URL' : function(err, req) {
assert.equal(req.redirectURL, 'https://www.example.com/oauth2/authorize?response_type=code&redirect_uri=https%3A%2F%2Fwww.example.net%2Fauth%2Fexample%2Fcallback&client_id=ABC123&type=web_server');
},
},
},
'strategy handling a request to be redirected for authorization with a callbackURL option override': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret',
callbackURL: 'https://www.example.net/auth/example/callback'
},
function(accessToken, refreshToken, profile, done) {}
);
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
req.user = user;
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
strategy.redirect = function(url) {
req.redirectURL = url;
self.callback(null, req);
}
process.nextTick(function () {
strategy.authenticate(req, { callbackURL: 'https://www.example.net/auth/example/other-callback' });
});
},
'should not call success or fail' : function(err, req) {
assert.isNull(err);
},
'should redirect to user authorization URL' : function(err, req) {
assert.equal(req.redirectURL, 'https://www.example.com/oauth2/authorize?response_type=code&redirect_uri=https%3A%2F%2Fwww.example.net%2Fauth%2Fexample%2Fother-callback&client_id=ABC123&type=web_server');
},
},
},
'strategy handling a request to be redirected for authorization with a relative callbackURL option override': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret',
callbackURL: 'https://www.example.net/auth/example/callback'
},
function(accessToken, refreshToken, profile, done) {}
);
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {
connection: { encrypted: true },
url: '/auth/example',
headers: {
'host': 'www.example.net',
}
};
strategy.success = function(user) {
req.user = user;
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
strategy.redirect = function(url) {
req.redirectURL = url;
self.callback(null, req);
}
process.nextTick(function () {
strategy.authenticate(req, { callbackURL: '/auth/example/another-callback' });
});
},
'should not call success or fail' : function(err, req) {
assert.isNull(err);
},
'should redirect to user authorization URL' : function(err, req) {
assert.equal(req.redirectURL, 'https://www.example.com/oauth2/authorize?response_type=code&redirect_uri=https%3A%2F%2Fwww.example.net%2Fauth%2Fexample%2Fanother-callback&client_id=ABC123&type=web_server');
},
},
},
'strategy handling a request to be redirected for authorization with a scope': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret',
callbackURL: 'https://www.example.net/auth/example/callback'
},
function(accessToken, refreshToken, profile, done) {}
);
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
req.user = user;
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
strategy.redirect = function(url) {
req.redirectURL = url;
self.callback(null, req);
}
process.nextTick(function () {
strategy.authenticate(req, { scope: 'permission' });
});
},
'should not call success or fail' : function(err, req) {
assert.isNull(err);
},
'should redirect to user authorization URL' : function(err, req) {
assert.equal(req.redirectURL, 'https://www.example.com/oauth2/authorize?response_type=code&redirect_uri=https%3A%2F%2Fwww.example.net%2Fauth%2Fexample%2Fcallback&scope=permission&client_id=ABC123&type=web_server');
},
},
},
'strategy handling a request to be redirected for authorization with multiple scopes': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret',
callbackURL: 'https://www.example.net/auth/example/callback'
},
function(accessToken, refreshToken, profile, done) {}
);
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
req.user = user;
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
strategy.redirect = function(url) {
req.redirectURL = url;
self.callback(null, req);
}
process.nextTick(function () {
strategy.authenticate(req, { scope: ['permission_1', 'permission_2' ] });
});
},
'should not call success or fail' : function(err, req) {
assert.isNull(err);
},
'should redirect to user authorization URL' : function(err, req) {
assert.equal(req.redirectURL, 'https://www.example.com/oauth2/authorize?response_type=code&redirect_uri=https%3A%2F%2Fwww.example.net%2Fauth%2Fexample%2Fcallback&scope=permission_1%20permission_2&client_id=ABC123&type=web_server');
},
},
},
'strategy handling a request to be redirected for authorization with multiple scopes and scope separator option': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret',
callbackURL: 'https://www.example.net/auth/example/callback',
scopeSeparator: ','
},
function(accessToken, refreshToken, profile, done) {}
);
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
req.user = user;
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
strategy.redirect = function(url) {
req.redirectURL = url;
self.callback(null, req);
}
process.nextTick(function () {
strategy.authenticate(req, { scope: ['permission_1', 'permission_2' ] });
});
},
'should not call success or fail' : function(err, req) {
assert.isNull(err);
},
'should redirect to user authorization URL' : function(err, req) {
assert.equal(req.redirectURL, 'https://www.example.com/oauth2/authorize?response_type=code&redirect_uri=https%3A%2F%2Fwww.example.net%2Fauth%2Fexample%2Fcallback&scope=permission_1%2Cpermission_2&client_id=ABC123&type=web_server');
},
},
},
'strategy handling a request to be redirected for authorization with extra params': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret',
callbackURL: 'https://www.example.net/auth/example/callback'
},
function(accessToken, refreshToken, profile, done) {}
);
strategy.authorizationParams = function(options) {
return { prompt: options.prompt };
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
req.user = user;
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
strategy.redirect = function(url) {
req.redirectURL = url;
self.callback(null, req);
}
process.nextTick(function () {
strategy.authenticate(req, { prompt: 'mobile' });
});
},
'should not call success or fail' : function(err, req) {
assert.isNull(err);
},
'should redirect to user authorization URL' : function(err, req) {
assert.equal(req.redirectURL, 'https://www.example.com/oauth2/authorize?prompt=mobile&response_type=code&redirect_uri=https%3A%2F%2Fwww.example.net%2Fauth%2Fexample%2Fcallback&client_id=ABC123&type=web_server');
},
},
},
'strategy handling a request to be redirected for authorization with scope and extra params': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret',
callbackURL: 'https://www.example.net/auth/example/callback'
},
function(accessToken, refreshToken, profile, done) {}
);
strategy.authorizationParams = function(options) {
return { prompt: options.prompt };
}
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
req.user = user;
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(new Error('should-not-be-called'));
}
strategy.redirect = function(url) {
req.redirectURL = url;
self.callback(null, req);
}
process.nextTick(function () {
strategy.authenticate(req, { scope: 'permission', prompt: 'mobile' });
});
},
'should not call success or fail' : function(err, req) {
assert.isNull(err);
},
'should redirect to user authorization URL' : function(err, req) {
assert.equal(req.redirectURL, 'https://www.example.com/oauth2/authorize?prompt=mobile&response_type=code&redirect_uri=https%3A%2F%2Fwww.example.net%2Fauth%2Fexample%2Fcallback&scope=permission&client_id=ABC123&type=web_server');
},
},
},
'strategy handling a request that has been denied': {
topic: function() {
var strategy = new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'ABC123',
clientSecret: 'secret',
callbackURL: 'https://www.example.net/auth/example/callback'
},
function(accessToken, refreshToken, profile, done) {}
);
return strategy;
},
'after augmenting with actions': {
topic: function(strategy) {
var self = this;
var req = {};
strategy.success = function(user) {
self.callback(new Error('should-not-be-called'));
}
strategy.fail = function() {
self.callback(null, req);
}
req.query = {};
req.query.error = 'access_denied';
process.nextTick(function () {
strategy.authenticate(req);
});
},
'should not call success' : function(err, req) {
assert.isNull(err);
},
'should call fail' : function(err, req) {
assert.isNotNull(req);
},
},
},
}).export(module);