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-oauth1/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.

122
express-server/node_modules/passport-oauth1/README.md generated vendored Normal file
View File

@ -0,0 +1,122 @@
# passport-oauth1
[![Build](https://img.shields.io/travis/jaredhanson/passport-oauth1.svg)](https://travis-ci.org/jaredhanson/passport-oauth1)
[![Coverage](https://img.shields.io/coveralls/jaredhanson/passport-oauth1.svg)](https://coveralls.io/r/jaredhanson/passport-oauth1)
[![Quality](https://img.shields.io/codeclimate/github/jaredhanson/passport-oauth1.svg?label=quality)](https://codeclimate.com/github/jaredhanson/passport-oauth1)
[![Dependencies](https://img.shields.io/david/jaredhanson/passport-oauth1.svg)](https://david-dm.org/jaredhanson/passport-oauth1)
General-purpose OAuth 1.0 authentication strategy for [Passport](http://passportjs.org/).
This module lets you authenticate using OAuth in your Node.js applications.
By plugging into Passport, OAuth 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 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 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-oauth1
## Usage
#### Configure Strategy
The OAuth authentication strategy authenticates users using a third-party
account and OAuth tokens. The provider's OAuth endpoints, as well as the
consumer key and secret, are specified as options. The strategy requires a
`verify` callback, which receives a token and profile, and calls `cb`
providing a user.
passport.use(new OAuth1Strategy({
requestTokenURL: 'https://www.example.com/oauth/request_token',
accessTokenURL: 'https://www.example.com/oauth/access_token',
userAuthorizationURL: 'https://www.example.com/oauth/authorize',
consumerKey: EXAMPLE_CONSUMER_KEY,
consumerSecret: EXAMPLE_CONSUMER_SECRET,
callbackURL: "http://127.0.0.1:3000/auth/example/callback",
signatureMethod: "RSA-SHA1"
},
function(token, tokenSecret, profile, cb) {
User.findOrCreate({ exampleId: profile.id }, function (err, user) {
return cb(err, user);
});
}
));
#### Authenticate Requests
Use `passport.authenticate()`, specifying the `'oauth'` strategy, to
authenticate requests.
For example, as route middleware in an [Express](http://expressjs.com/)
application:
app.get('/auth/example',
passport.authenticate('oauth'));
app.get('/auth/example/callback',
passport.authenticate('oauth', { failureRedirect: '/login' }),
function(req, res) {
// Successful authentication, redirect home.
res.redirect('/');
});
## Related Modules
- [passport-oauth2](https://github.com/jaredhanson/passport-oauth2) — OAuth 2.0 authentication strategy
- [passport-http-oauth](https://github.com/jaredhanson/passport-http-oauth) — OAuth authentication strategy for APIs
- [oauthorize](https://github.com/jaredhanson/oauthorize) — OAuth service provider 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,45 @@
/**
* `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 constructor.
module.exports = InternalOAuthError;

View File

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

View File

@ -0,0 +1,38 @@
function SessionStore(options) {
if (!options.key) { throw new TypeError('Session-based request token store requires a session key'); }
this._key = options.key;
}
SessionStore.prototype.get = function(req, token, cb) {
if (!req.session) { return cb(new Error('OAuth authentication requires session support. Did you forget to use express-session middleware?')); }
// 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[this._key]) { return cb(new Error('Failed to find request token in session')); }
var tokenSecret = req.session[this._key].oauth_token_secret;
return cb(null, tokenSecret);
};
SessionStore.prototype.set = function(req, token, tokenSecret, cb) {
if (!req.session) { return cb(new Error('OAuth authentication requires session support. Did you forget to use express-session middleware?')); }
if (!req.session[this._key]) { req.session[this._key] = {}; }
req.session[this._key].oauth_token = token;
req.session[this._key].oauth_token_secret = tokenSecret;
cb();
};
SessionStore.prototype.destroy = function(req, token, cb) {
delete req.session[this._key].oauth_token;
delete req.session[this._key].oauth_token_secret;
if (Object.keys(req.session[this._key]).length === 0) {
delete req.session[this._key];
}
cb();
};
module.exports = SessionStore;

View File

@ -0,0 +1,402 @@
// Load modules.
var passport = require('passport-strategy')
, url = require('url')
, util = require('util')
, utils = require('./utils')
, OAuth = require('oauth').OAuth
, SessionRequestTokenStore = require('./requesttoken/session')
, InternalOAuthError = require('./errors/internaloautherror');
/**
* Creates an instance of `OAuthStrategy`.
*
* 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, for which the function
* signature is:
*
* function(token, tokenSecret, profile, cb) { ... }
*
* The verify callback is responsible for finding or creating the user, and
* invoking `cb` 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:
*
* - `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
* - 'signatureMethod' signature method used to sign the request (default: 'HMAC-SHA1')
* - `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 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, cb) {
* User.findOrCreate(..., function (err, user) {
* cb(err, user);
* });
* }
* ));
*
* @constructor
* @param {Object} options
* @param {Function} verify
* @api public
*/
function OAuthStrategy(options, verify) {
if (typeof options == 'function') {
verify = options;
options = undefined;
}
options = options || {};
if (!verify) { throw new TypeError('OAuthStrategy requires a verify callback'); }
if (!options.requestTokenURL) { throw new TypeError('OAuthStrategy requires a requestTokenURL option'); }
if (!options.accessTokenURL) { throw new TypeError('OAuthStrategy requires a accessTokenURL option'); }
if (!options.userAuthorizationURL) { throw new TypeError('OAuthStrategy requires a userAuthorizationURL option'); }
if (!options.consumerKey) { throw new TypeError('OAuthStrategy requires a consumerKey option'); }
if (options.consumerSecret === undefined) { throw new TypeError('OAuthStrategy requires a consumerSecret option'); }
passport.Strategy.call(this);
this.name = 'oauth';
this._verify = verify;
// 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', null, options.signatureMethod || 'HMAC-SHA1',
null, options.customHeaders);
this._userAuthorizationURL = options.userAuthorizationURL;
this._callbackURL = options.callbackURL;
this._key = options.sessionKey || 'oauth';
this._requestTokenStore = options.requestTokenStore || new SessionRequestTokenStore({ key: this._key });
this._trustProxy = options.proxy;
this._passReqToCallback = options.passReqToCallback;
this._skipUserProfile = (options.skipUserProfile === undefined) ? false : options.skipUserProfile;
}
// 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) {
options = options || {};
var self = this;
var meta = {
requestTokenURL: this._oauth._requestUrl,
accessTokenURL: this._oauth._accessUrl,
userAuthorizationURL: this._userAuthorizationURL,
consumerKey: this._oauth._consumerKey
}
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.
var oauthToken = req.query.oauth_token;
function loaded(err, oauthTokenSecret, state) {
if (err) { return self.error(err); }
if (!oauthTokenSecret) {
return self.fail(state, 403);
}
// NOTE: The oauth_verifier parameter will be supplied in the query portion
// of the redirect URL, if the server supports OAuth 1.0a.
var oauthVerifier = req.query.oauth_verifier || null;
self._oauth.getOAuthAccessToken(oauthToken, oauthTokenSecret, oauthVerifier, function(err, token, tokenSecret, params) {
if (err) { return self.error(self._createOAuthError('Failed to obtain access token', err)); }
function destroyed(err) {
if (err) { return self.error(err); }
self._loadUserProfile(token, tokenSecret, params, 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, token, tokenSecret, params, profile, verified);
} else { // arity == 5
self._verify(req, token, tokenSecret, profile, verified);
}
} else {
var arity = self._verify.length;
if (arity == 5) {
self._verify(token, tokenSecret, params, profile, verified);
} else { // arity == 4
self._verify(token, tokenSecret, profile, verified);
}
}
} catch (ex) {
return self.error(ex);
}
});
}
// 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
// store.
try {
var arity = self._requestTokenStore.destroy.length;
if (arity == 4) {
self._requestTokenStore.destroy(req, oauthToken, meta, destroyed);
} else { // arity == 3
self._requestTokenStore.destroy(req, oauthToken, destroyed);
}
} catch (ex) {
return self.error(ex);
}
});
}
try {
var arity = self._requestTokenStore.get.length;
if (arity == 4) {
this._requestTokenStore.get(req, oauthToken, meta, loaded);
} else { // arity == 3
this._requestTokenStore.get(req, oauthToken, loaded);
}
} catch (ex) {
return this.error(ex);
}
} 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);
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);
}
}
params.oauth_callback = callbackURL;
this._oauth.getOAuthRequestToken(params, function(err, token, tokenSecret, params) {
if (err) { return self.error(self._createOAuthError('Failed to obtain request token', err)); }
// NOTE: params will contain an oauth_callback_confirmed property set to
// true, if the server supports OAuth 1.0a.
// { oauth_callback_confirmed: 'true' }
function stored(err) {
if (err) { return self.error(err); }
var parsed = url.parse(self._userAuthorizationURL, true);
parsed.query.oauth_token = token;
if (!params.oauth_callback_confirmed && callbackURL) {
// NOTE: If oauth_callback_confirmed=true is not present when issuing a
// request token, the server does not support OAuth 1.0a. In this
// circumstance, `oauth_callback` is passed when redirecting the
// user to the service provider.
parsed.query.oauth_callback = callbackURL;
}
utils.merge(parsed.query, self.userAuthorizationParams(options));
delete parsed.search;
var location = url.format(parsed);
self.redirect(location);
}
try {
var arity = self._requestTokenStore.set.length;
if (arity == 5) {
self._requestTokenStore.set(req, token, tokenSecret, meta, stored);
} else { // arity == 4
self._requestTokenStore.set(req, token, tokenSecret, stored);
}
} catch (ex) {
return self.error(ex);
}
});
}
};
/**
* 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} token
* @param {String} tokenSecret
* @param {Object} params
* @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 {};
};
/**
* Return extra parameters to be included in the user authorization request.
*
* Some OAuth providers allow additional, non-standard parameters to be included
* when requesting authorization. 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.userAuthorizationParams = function(options) {
return {};
};
/**
* Parse error response from OAuth endpoint.
*
* OAuth-based authentication strategies can overrride this function in order to
* parse error responses received from the request token and access token
* endpoints, allowing the most informative message to be displayed.
*
* If this function is not overridden, a generic error will be thrown.
*
* @param {String} body
* @param {Number} status
* @return {Error}
* @api protected
*/
OAuthStrategy.prototype.parseErrorResponse = function(body, status) {
return null;
};
/**
* 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();
}
};
/**
* Create an OAuth error.
*
* @param {String} message
* @param {Object|Error} err
* @api private
*/
OAuthStrategy.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 = OAuthStrategy;

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,77 @@
{
"_from": "passport-oauth1@1.x.x",
"_id": "passport-oauth1@1.1.0",
"_inBundle": false,
"_integrity": "sha1-p96YiiEfnPRoc3cTDqdN8ycwyRg=",
"_location": "/passport-oauth1",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "passport-oauth1@1.x.x",
"name": "passport-oauth1",
"escapedName": "passport-oauth1",
"rawSpec": "1.x.x",
"saveSpec": null,
"fetchSpec": "1.x.x"
},
"_requiredBy": [
"/passport-google-oauth1"
],
"_resolved": "https://registry.npmjs.org/passport-oauth1/-/passport-oauth1-1.1.0.tgz",
"_shasum": "a7de988a211f9cf4687377130ea74df32730c918",
"_spec": "passport-oauth1@1.x.x",
"_where": "C:\\Users\\Georg\\GitHub\\SmartShopper\\express-server\\node_modules\\passport-google-oauth1",
"author": {
"name": "Jared Hanson",
"email": "jaredhanson@gmail.com",
"url": "http://www.jaredhanson.net/"
},
"bugs": {
"url": "http://github.com/jaredhanson/passport-oauth1/issues"
},
"bundleDependencies": false,
"dependencies": {
"oauth": "0.9.x",
"passport-strategy": "1.x.x",
"utils-merge": "1.x.x"
},
"deprecated": false,
"description": "OAuth 1.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-oauth1#readme",
"keywords": [
"passport",
"auth",
"authn",
"authentication",
"authz",
"authorization",
"oauth"
],
"license": "MIT",
"licenses": [
{
"type": "MIT",
"url": "http://opensource.org/licenses/MIT"
}
],
"main": "./lib",
"name": "passport-oauth1",
"repository": {
"type": "git",
"url": "git://github.com/jaredhanson/passport-oauth1.git"
},
"scripts": {
"test": "mocha --reporter spec --require test/bootstrap/node test/*.test.js test/**/*.test.js"
},
"version": "1.1.0"
}