GoogleOauth2.0 First implementation

First try for GoogleOauth2.0
This commit is contained in:
Georg Reisinger
2018-10-26 14:02:15 +02:00
parent 216a04e233
commit b171f1646c
1880 changed files with 912953 additions and 7 deletions

View File

@ -0,0 +1,8 @@
Makefile
docs/
examples/
reports/
test/
.jshintrc
.travis.yml

20
express-server/node_modules/passport-oauth2/LICENSE generated vendored Normal file
View File

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2011-2016 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.

124
express-server/node_modules/passport-oauth2/README.md generated vendored Normal file
View File

@ -0,0 +1,124 @@
# passport-oauth2
[![Build](https://img.shields.io/travis/jaredhanson/passport-oauth2.svg)](https://travis-ci.org/jaredhanson/passport-oauth2)
[![Coverage](https://img.shields.io/coveralls/jaredhanson/passport-oauth2.svg)](https://coveralls.io/r/jaredhanson/passport-oauth2)
[![Quality](https://img.shields.io/codeclimate/github/jaredhanson/passport-oauth2.svg?label=quality)](https://codeclimate.com/github/jaredhanson/passport-oauth2)
[![Dependencies](https://img.shields.io/david/jaredhanson/passport-oauth2.svg)](https://david-dm.org/jaredhanson/passport-oauth2)
General-purpose OAuth 2.0 authentication strategy for [Passport](http://passportjs.org/).
This module lets you authenticate using OAuth 2.0 in your Node.js applications.
By plugging into Passport, OAuth 2.0 authentication can be easily and
unobtrusively integrated into any application or framework that supports
[Connect](http://www.senchalabs.org/connect/)-style middleware, including
[Express](http://expressjs.com/).
Note that this strategy provides generic OAuth 2.0 support. In many cases, a
provider-specific strategy can be used instead, which cuts down on unnecessary
configuration, and accommodates any provider-specific quirks. See the
[list](https://github.com/jaredhanson/passport/wiki/Strategies) for supported
providers.
Developers who need to implement authentication against an OAuth 2.0 provider
that is not already supported are encouraged to sub-class this strategy. If you
choose to open source the new provider-specific strategy, please add it to the
list so other people can find it.
## Install
$ npm install passport-oauth2
## Usage
#### Configure Strategy
The OAuth 2.0 authentication strategy authenticates users using a third-party
account and OAuth 2.0 tokens. The provider's OAuth 2.0 endpoints, as well as
the client identifer and secret, are specified as options. The strategy
requires a `verify` callback, which receives an access token and profile,
and calls `cb` providing a user.
```js
passport.use(new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: EXAMPLE_CLIENT_ID,
clientSecret: EXAMPLE_CLIENT_SECRET,
callbackURL: "http://localhost:3000/auth/example/callback"
},
function(accessToken, refreshToken, profile, cb) {
User.findOrCreate({ exampleId: profile.id }, function (err, user) {
return cb(err, user);
});
}
));
```
#### Authenticate Requests
Use `passport.authenticate()`, specifying the `'oauth2'` strategy, to
authenticate requests.
For example, as route middleware in an [Express](http://expressjs.com/)
application:
```js
app.get('/auth/example',
passport.authenticate('oauth2'));
app.get('/auth/example/callback',
passport.authenticate('oauth2', { failureRedirect: '/login' }),
function(req, res) {
// Successful authentication, redirect home.
res.redirect('/');
});
```
## Related Modules
- [passport-oauth1](https://github.com/jaredhanson/passport-oauth1) — OAuth 1.0 authentication strategy
- [passport-http-bearer](https://github.com/jaredhanson/passport-http-bearer) — Bearer token authentication strategy for APIs
- [OAuth2orize](https://github.com/jaredhanson/oauth2orize) — OAuth 2.0 authorization server toolkit
## Contributing
#### Tests
The test suite is located in the `test/` directory. All new features are
expected to have corresponding test cases. Ensure that the complete test suite
passes by executing:
```bash
$ make test
```
#### Coverage
All new feature development is expected to have test coverage. Patches that
increse test coverage are happily accepted. Coverage reports can be viewed by
executing:
```bash
$ make test-cov
$ make view-cov
```
## Support
#### Funding
This software is provided to you as open source, free of charge. The time and
effort to develop and maintain this project is dedicated by [@jaredhanson](https://github.com/jaredhanson).
If you (or your employer) benefit from this project, please consider a financial
contribution. Your contribution helps continue the efforts that produce this
and other open source software.
Funds are accepted via [PayPal](https://paypal.me/jaredhanson), [Venmo](https://venmo.com/jaredhanson),
and [other](http://jaredhanson.net/pay) methods. Any amount is appreciated.
## License
[The MIT License](http://opensource.org/licenses/MIT)
Copyright (c) 2011-2016 Jared Hanson <[http://jaredhanson.net/](http://jaredhanson.net/)>

View File

@ -0,0 +1,44 @@
/**
* `AuthorizationError` error.
*
* AuthorizationError represents an error in response to an authorization
* request. For details, refer to RFC 6749, section 4.1.2.1.
*
* References:
* - [The OAuth 2.0 Authorization Framework](http://tools.ietf.org/html/rfc6749)
*
* @constructor
* @param {String} [message]
* @param {String} [code]
* @param {String} [uri]
* @param {Number} [status]
* @api public
*/
function AuthorizationError(message, code, uri, status) {
if (!status) {
switch (code) {
case 'access_denied': status = 403; break;
case 'server_error': status = 502; break;
case 'temporarily_unavailable': status = 503; break;
}
}
Error.call(this);
Error.captureStackTrace(this, this.constructor);
this.name = this.constructor.name;
this.message = message;
this.code = code || 'server_error';
this.uri = uri;
this.status = status || 500;
}
/**
* Inherit from `Error`.
*/
AuthorizationError.prototype.__proto__ = Error.prototype;
/**
* Expose `AuthorizationError`.
*/
module.exports = AuthorizationError;

View File

@ -0,0 +1,49 @@
/**
* `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.
*
* @constructor
* @param {String} [message]
* @param {Object|Error} [err]
* @api public
*/
function InternalOAuthError(message, err) {
Error.call(this);
Error.captureStackTrace(this, this.constructor);
this.name = this.constructor.name;
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.name;
if (this.message) { m += ': ' + this.message; }
if (this.oauthError) {
if (this.oauthError instanceof Error) {
m = this.oauthError.toString();
} else if (this.oauthError.statusCode && this.oauthError.data) {
m += ' (status: ' + this.oauthError.statusCode + ' data: ' + this.oauthError.data + ')';
}
}
return m;
};
/**
* Expose `InternalOAuthError`.
*/
module.exports = InternalOAuthError;

View File

@ -0,0 +1,36 @@
/**
* `TokenError` error.
*
* TokenError represents an error received from a token endpoint. For details,
* refer to RFC 6749, section 5.2.
*
* References:
* - [The OAuth 2.0 Authorization Framework](http://tools.ietf.org/html/rfc6749)
*
* @constructor
* @param {String} [message]
* @param {String} [code]
* @param {String} [uri]
* @param {Number} [status]
* @api public
*/
function TokenError(message, code, uri, status) {
Error.call(this);
Error.captureStackTrace(this, this.constructor);
this.name = this.constructor.name;
this.message = message;
this.code = code || 'invalid_request';
this.uri = uri;
this.status = status || 500;
}
/**
* Inherit from `Error`.
*/
TokenError.prototype.__proto__ = Error.prototype;
/**
* Expose `TokenError`.
*/
module.exports = TokenError;

View File

@ -0,0 +1,16 @@
// Load modules.
var Strategy = require('./strategy')
, AuthorizationError = require('./errors/authorizationerror')
, TokenError = require('./errors/tokenerror')
, InternalOAuthError = require('./errors/internaloautherror');
// Expose Strategy.
exports = module.exports = Strategy;
// Exports.
exports.Strategy = Strategy;
exports.AuthorizationError = AuthorizationError;
exports.TokenError = TokenError;
exports.InternalOAuthError = InternalOAuthError;

View File

@ -0,0 +1,13 @@
function NullStore(options) {
}
NullStore.prototype.store = function(req, cb) {
cb();
}
NullStore.prototype.verify = function(req, providedState, cb) {
cb(null, true);
}
module.exports = NullStore;

View File

@ -0,0 +1,85 @@
var uid = require('uid2');
/**
* Creates an instance of `SessionStore`.
*
* This is the state store implementation for the OAuth2Strategy used when
* the `state` option is enabled. It generates a random state and stores it in
* `req.session` and verifies it when the service provider redirects the user
* back to the application.
*
* This state store requires session support. If no session exists, an error
* will be thrown.
*
* Options:
*
* - `key` The key in the session under which to store the state
*
* @constructor
* @param {Object} options
* @api public
*/
function SessionStore(options) {
if (!options.key) { throw new TypeError('Session-based state store requires a session key'); }
this._key = options.key;
}
/**
* Store request state.
*
* This implementation simply generates a random string and stores the value in
* the session, where it will be used for verification when the user is
* redirected back to the application.
*
* @param {Object} req
* @param {Function} callback
* @api protected
*/
SessionStore.prototype.store = function(req, callback) {
if (!req.session) { return callback(new Error('OAuth 2.0 authentication requires session support when using state. Did you forget to use express-session middleware?')); }
var key = this._key;
var state = uid(24);
if (!req.session[key]) { req.session[key] = {}; }
req.session[key].state = state;
callback(null, state);
};
/**
* Verify request state.
*
* This implementation simply compares the state parameter in the request to the
* value generated earlier and stored in the session.
*
* @param {Object} req
* @param {String} providedState
* @param {Function} callback
* @api protected
*/
SessionStore.prototype.verify = function(req, providedState, callback) {
if (!req.session) { return callback(new Error('OAuth 2.0 authentication requires session support when using state. Did you forget to use express-session middleware?')); }
var key = this._key;
if (!req.session[key]) {
return callback(null, false, { message: 'Unable to verify authorization request state.' });
}
var state = req.session[key].state;
if (!state) {
return callback(null, false, { message: 'Unable to verify authorization request state.' });
}
delete req.session[key].state;
if (Object.keys(req.session[key]).length === 0) {
delete req.session[key];
}
if (state !== providedState) {
return callback(null, false, { message: 'Invalid authorization request state.' });
}
return callback(null, true);
};
// Expose constructor.
module.exports = SessionStore;

View File

@ -0,0 +1,385 @@
// Load modules.
var passport = require('passport-strategy')
, url = require('url')
, util = require('util')
, utils = require('./utils')
, OAuth2 = require('oauth').OAuth2
, NullStateStore = require('./state/null')
, SessionStateStore = require('./state/session')
, AuthorizationError = require('./errors/authorizationerror')
, TokenError = require('./errors/tokenerror')
, InternalOAuthError = require('./errors/internaloautherror');
/**
* Creates an instance of `OAuth2Strategy`.
*
* The OAuth 2.0 authentication strategy authenticates requests using the OAuth
* 2.0 framework.
*
* 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, for which the function
* signature is:
*
* function(accessToken, refreshToken, profile, done) { ... }
*
* The verify callback is responsible for finding or creating the user, and
* invoking `done` with the following arguments:
*
* done(err, user, info);
*
* `user` should be set to `false` to indicate an authentication failure.
* Additional `info` can optionally be passed as a third argument, typically
* used to display informational messages. 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
* - `passReqToCallback` when `true`, `req` is the first argument to the verify callback (default: `false`)
*
* 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);
* });
* }
* ));
*
* @constructor
* @param {Object} options
* @param {Function} verify
* @api public
*/
function OAuth2Strategy(options, verify) {
if (typeof options == 'function') {
verify = options;
options = undefined;
}
options = options || {};
if (!verify) { throw new TypeError('OAuth2Strategy requires a verify callback'); }
if (!options.authorizationURL) { throw new TypeError('OAuth2Strategy requires a authorizationURL option'); }
if (!options.tokenURL) { throw new TypeError('OAuth2Strategy requires a tokenURL option'); }
if (!options.clientID) { throw new TypeError('OAuth2Strategy requires a clientID option'); }
passport.Strategy.call(this);
this.name = 'oauth2';
this._verify = verify;
// 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, options.customHeaders);
this._callbackURL = options.callbackURL;
this._scope = options.scope;
this._scopeSeparator = options.scopeSeparator || ' ';
this._key = options.sessionKey || ('oauth2:' + url.parse(options.authorizationURL).hostname);
if (options.store) {
this._stateStore = options.store;
} else {
if (options.state) {
this._stateStore = new SessionStateStore({ key: this._key });
} else {
this._stateStore = new NullStateStore();
}
}
this._trustProxy = options.proxy;
this._passReqToCallback = options.passReqToCallback;
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) {
if (req.query.error == 'access_denied') {
return this.fail({ message: req.query.error_description });
} else {
return this.error(new AuthorizationError(req.query.error_description, req.query.error, req.query.error_uri));
}
}
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, { proxy: this._trustProxy }), callbackURL);
}
}
var meta = {
authorizationURL: this._oauth2._authorizeUrl,
tokenURL: this._oauth2._accessTokenUrl,
clientID: this._oauth2._clientId
}
if (req.query && req.query.code) {
function loaded(err, ok, state) {
if (err) { return self.error(err); }
if (!ok) {
return self.fail(state, 403);
}
var code = req.query.code;
var params = self.tokenParams(options);
params.grant_type = 'authorization_code';
if (callbackURL) { params.redirect_uri = callbackURL; }
self._oauth2.getOAuthAccessToken(code, params,
function(err, accessToken, refreshToken, params) {
if (err) { return self.error(self._createOAuthError('Failed to obtain access token', err)); }
self._loadUserProfile(accessToken, function(err, profile) {
if (err) { return self.error(err); }
function verified(err, user, info) {
if (err) { return self.error(err); }
if (!user) { return self.fail(info); }
info = info || {};
if (state) { info.state = state; }
self.success(user, info);
}
try {
if (self._passReqToCallback) {
var arity = self._verify.length;
if (arity == 6) {
self._verify(req, accessToken, refreshToken, params, profile, verified);
} else { // arity == 5
self._verify(req, accessToken, refreshToken, profile, verified);
}
} else {
var arity = self._verify.length;
if (arity == 5) {
self._verify(accessToken, refreshToken, params, profile, verified);
} else { // arity == 4
self._verify(accessToken, refreshToken, profile, verified);
}
}
} catch (ex) {
return self.error(ex);
}
});
}
);
}
var state = req.query.state;
try {
var arity = this._stateStore.verify.length;
if (arity == 4) {
this._stateStore.verify(req, state, meta, loaded);
} else { // arity == 3
this._stateStore.verify(req, state, loaded);
}
} catch (ex) {
return this.error(ex);
}
} else {
var params = this.authorizationParams(options);
params.response_type = 'code';
if (callbackURL) { params.redirect_uri = callbackURL; }
var scope = options.scope || this._scope;
if (scope) {
if (Array.isArray(scope)) { scope = scope.join(this._scopeSeparator); }
params.scope = scope;
}
var state = options.state;
if (state) {
params.state = state;
var parsed = url.parse(this._oauth2._authorizeUrl, true);
utils.merge(parsed.query, params);
parsed.query['client_id'] = this._oauth2._clientId;
delete parsed.search;
var location = url.format(parsed);
this.redirect(location);
} else {
function stored(err, state) {
if (err) { return self.error(err); }
if (state) { params.state = state; }
var parsed = url.parse(self._oauth2._authorizeUrl, true);
utils.merge(parsed.query, params);
parsed.query['client_id'] = self._oauth2._clientId;
delete parsed.search;
var location = url.format(parsed);
self.redirect(location);
}
try {
var arity = this._stateStore.store.length;
if (arity == 3) {
this._stateStore.store(req, meta, stored);
} else { // arity == 2
this._stateStore.store(req, stored);
}
} catch (ex) {
return this.error(ex);
}
}
}
};
/**
* 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 {};
};
/**
* Return extra parameters to be included in the token request.
*
* Some OAuth 2.0 providers allow additional, non-standard parameters to be
* included when requesting an access token. 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.
*
* @return {Object}
* @api protected
*/
OAuth2Strategy.prototype.tokenParams = function(options) {
return {};
};
/**
* Parse error response from OAuth 2.0 endpoint.
*
* OAuth 2.0-based authentication strategies can overrride this function in
* order to parse error responses received from the token endpoint, allowing the
* most informative message to be displayed.
*
* If this function is not overridden, the body will be parsed in accordance
* with RFC 6749, section 5.2.
*
* @param {String} body
* @param {Number} status
* @return {Error}
* @api protected
*/
OAuth2Strategy.prototype.parseErrorResponse = function(body, status) {
var json = JSON.parse(body);
if (json.error) {
return new TokenError(json.error_description, json.error, json.error_uri);
}
return null;
};
/**
* 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();
}
};
/**
* Create an OAuth error.
*
* @param {String} message
* @param {Object|Error} err
* @api private
*/
OAuth2Strategy.prototype._createOAuthError = function(message, err) {
var e;
if (err.statusCode && err.data) {
try {
e = this.parseErrorResponse(err.data, err.statusCode);
} catch (_) {}
}
if (!e) { e = new InternalOAuthError(message, err); }
return e;
};
// Expose constructor.
module.exports = OAuth2Strategy;

View File

@ -0,0 +1,32 @@
exports.merge = require('utils-merge');
/**
* 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, assuming that the proxy has been flagged as trusted.
*
* @param {http.IncomingMessage} req
* @param {Object} [options]
* @return {String}
* @api private
*/
exports.originalURL = function(req, options) {
options = options || {};
var app = req.app;
if (app && app.get && app.get('trust proxy')) {
options.proxy = true;
}
var trustProxy = options.proxy;
var proto = (req.headers['x-forwarded-proto'] || '').toLowerCase()
, tls = req.connection.encrypted || (trustProxy && 'https' == proto.split(/\s*,\s*/)[0])
, host = (trustProxy && req.headers['x-forwarded-host']) || req.headers.host
, protocol = tls ? 'https' : 'http'
, path = req.url || '';
return protocol + '://' + host + path;
};

View File

@ -0,0 +1,79 @@
{
"_from": "passport-oauth2@1.x.x",
"_id": "passport-oauth2@1.4.0",
"_inBundle": false,
"_integrity": "sha1-9i+BWDy+EmCb585vFguTlaJ7hq0=",
"_location": "/passport-oauth2",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "passport-oauth2@1.x.x",
"name": "passport-oauth2",
"escapedName": "passport-oauth2",
"rawSpec": "1.x.x",
"saveSpec": null,
"fetchSpec": "1.x.x"
},
"_requiredBy": [
"/passport-google-oauth20"
],
"_resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.4.0.tgz",
"_shasum": "f62f81583cbe12609be7ce6f160b9395a27b86ad",
"_spec": "passport-oauth2@1.x.x",
"_where": "C:\\Users\\Georg\\GitHub\\SmartShopper\\express-server\\node_modules\\passport-google-oauth20",
"author": {
"name": "Jared Hanson",
"email": "jaredhanson@gmail.com",
"url": "http://www.jaredhanson.net/"
},
"bugs": {
"url": "http://github.com/jaredhanson/passport-oauth2/issues"
},
"bundleDependencies": false,
"dependencies": {
"oauth": "0.9.x",
"passport-strategy": "1.x.x",
"uid2": "0.0.x",
"utils-merge": "1.x.x"
},
"deprecated": false,
"description": "OAuth 2.0 authentication strategy for Passport.",
"devDependencies": {
"chai": "2.x.x",
"chai-passport-strategy": "1.x.x",
"make-node": "0.3.x",
"mocha": "2.x.x"
},
"engines": {
"node": ">= 0.4.0"
},
"homepage": "https://github.com/jaredhanson/passport-oauth2#readme",
"keywords": [
"passport",
"auth",
"authn",
"authentication",
"authz",
"authorization",
"oauth",
"oauth2"
],
"license": "MIT",
"licenses": [
{
"type": "MIT",
"url": "http://opensource.org/licenses/MIT"
}
],
"main": "./lib",
"name": "passport-oauth2",
"repository": {
"type": "git",
"url": "git://github.com/jaredhanson/passport-oauth2.git"
},
"scripts": {
"test": "mocha --reporter spec --require test/bootstrap/node test/*.test.js test/**/*.test.js"
},
"version": "1.4.0"
}