diff options
Diffstat (limited to 'node_modules/passport-google-oauth20/lib')
6 files changed, 342 insertions, 0 deletions
diff --git a/node_modules/passport-google-oauth20/lib/errors/googleplusapierror.js b/node_modules/passport-google-oauth20/lib/errors/googleplusapierror.js new file mode 100644 index 0000000..57a9bd2 --- /dev/null +++ b/node_modules/passport-google-oauth20/lib/errors/googleplusapierror.js @@ -0,0 +1,25 @@ +/** + * `GooglePlusAPIError` error. + * + * References: + * - https://developers.google.com/+/web/api/rest/ + * + * @constructor + * @param {string} [message] + * @param {number} [code] + * @access public + */ +function GooglePlusAPIError(message, code) { + Error.call(this); + Error.captureStackTrace(this, arguments.callee); + this.name = 'GooglePlusAPIError'; + this.message = message; + this.code = code; +} + +// Inherit from `Error`. +GooglePlusAPIError.prototype.__proto__ = Error.prototype; + + +// Expose constructor. +module.exports = GooglePlusAPIError; diff --git a/node_modules/passport-google-oauth20/lib/errors/userinfoerror.js b/node_modules/passport-google-oauth20/lib/errors/userinfoerror.js new file mode 100644 index 0000000..0b2c487 --- /dev/null +++ b/node_modules/passport-google-oauth20/lib/errors/userinfoerror.js @@ -0,0 +1,22 @@ +/** + * `UserInfoError` error. + * + * @constructor + * @param {string} [message] + * @param {string} [code] + * @access public + */ +function UserInfoError(message, code) { + Error.call(this); + Error.captureStackTrace(this, arguments.callee); + this.name = 'UserInfoError'; + this.message = message; + this.code = code; +} + +// Inherit from `Error`. +UserInfoError.prototype.__proto__ = Error.prototype; + + +// Expose constructor. +module.exports = UserInfoError; diff --git a/node_modules/passport-google-oauth20/lib/index.js b/node_modules/passport-google-oauth20/lib/index.js new file mode 100644 index 0000000..af2282d --- /dev/null +++ b/node_modules/passport-google-oauth20/lib/index.js @@ -0,0 +1,9 @@ +// Load modules. +var Strategy = require('./strategy'); + + +// Expose Strategy. +exports = module.exports = Strategy; + +// Exports. +exports.Strategy = Strategy; diff --git a/node_modules/passport-google-oauth20/lib/profile/googleplus.js b/node_modules/passport-google-oauth20/lib/profile/googleplus.js new file mode 100644 index 0000000..0607ba1 --- /dev/null +++ b/node_modules/passport-google-oauth20/lib/profile/googleplus.js @@ -0,0 +1,47 @@ +/** + * Parse profile. + * + * Parses user profiles as fetched from Google's Google+ API. + * + * The amount of detail in the profile varies based on the scopes granted by the + * user. The following scope values add additional data: + * + * `https://www.googleapis.com/auth/plus.login` - recommended login scope + * `profile` - basic profile information + * `email` - email address + * + * References: + * - https://developers.google.com/+/web/api/rest/latest/people/get + * - https://developers.google.com/+/web/api/rest/ + * - https://developers.google.com/+/web/api/rest/oauth + * + * @param {object|string} json + * @return {object} + * @access public + */ +exports.parse = function(json) { + if ('string' == typeof json) { + json = JSON.parse(json); + } + + var profile = {} + , i, len; + profile.id = json.id; + profile.displayName = json.displayName; + if (json.name) { + profile.name = { familyName: json.name.familyName, + givenName: json.name.givenName }; + } + if (json.emails) { + profile.emails = []; + for (i = 0, len = json.emails.length; i < len; ++i) { + profile.emails.push({ value: json.emails[i].value, type: json.emails[i].type }) + } + } + if (json.image) { + profile.photos = [{ value: json.image.url }]; + } + profile.gender = json.gender; + + return profile; +}; diff --git a/node_modules/passport-google-oauth20/lib/profile/openid.js b/node_modules/passport-google-oauth20/lib/profile/openid.js new file mode 100644 index 0000000..2056feb --- /dev/null +++ b/node_modules/passport-google-oauth20/lib/profile/openid.js @@ -0,0 +1,40 @@ +/** + * Parse profile. + * + * Parses user profiles as fetched from Google's OpenID Connect-compatible user + * info endpoint. + * + * The amount of detail in the profile varies based on the scopes granted by the + * user. The following scope values add additional data: + * + * `profile` - basic profile information + * `email` - email address + * + * References: + * - https://developers.google.com/identity/protocols/OpenIDConnect + * + * @param {object|string} json + * @return {object} + * @access public + */ +exports.parse = function(json) { + if ('string' == typeof json) { + json = JSON.parse(json); + } + + var profile = {}; + profile.id = json.sub; + profile.displayName = json.name; + if (json.family_name || json.given_name) { + profile.name = { familyName: json.family_name, + givenName: json.given_name }; + } + if (json.email) { + profile.emails = [ { value: json.email, verified: json.email_verified } ]; + } + if (json.picture) { + profile.photos = [{ value: json.picture }]; + } + + return profile; +}; diff --git a/node_modules/passport-google-oauth20/lib/strategy.js b/node_modules/passport-google-oauth20/lib/strategy.js new file mode 100644 index 0000000..274cd92 --- /dev/null +++ b/node_modules/passport-google-oauth20/lib/strategy.js @@ -0,0 +1,199 @@ +// Load modules. +var OAuth2Strategy = require('passport-oauth2') + , util = require('util') + , uri = require('url') + , GooglePlusProfile = require('./profile/googleplus') + , OpenIDProfile = require('./profile/openid') + , InternalOAuthError = require('passport-oauth2').InternalOAuthError + , GooglePlusAPIError = require('./errors/googleplusapierror') + , UserInfoError = require('./errors/userinfoerror'); + + +/** + * `Strategy` constructor. + * + * The Google authentication strategy authenticates requests by delegating to + * Google using the OAuth 2.0 protocol. + * + * Applications must supply a `verify` callback which accepts an `accessToken`, + * `refreshToken` and service-specific `profile`, and then calls the `cb` + * 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: + * - `clientID` your Google application's client id + * - `clientSecret` your Google application's client secret + * - `callbackURL` URL to which Google will redirect the user after granting authorization + * + * Examples: + * + * passport.use(new GoogleStrategy({ + * clientID: '123-456-789', + * clientSecret: 'shhh-its-a-secret' + * callbackURL: 'https://www.example.net/auth/google/callback' + * }, + * function(accessToken, refreshToken, profile, cb) { + * User.findOrCreate(..., function (err, user) { + * cb(err, user); + * }); + * } + * )); + * + * @constructor + * @param {object} options + * @param {function} verify + * @access public + */ +function Strategy(options, verify) { + options = options || {}; + options.authorizationURL = options.authorizationURL || 'https://accounts.google.com/o/oauth2/v2/auth'; + options.tokenURL = options.tokenURL || 'https://www.googleapis.com/oauth2/v4/token'; + + OAuth2Strategy.call(this, options, verify); + this.name = 'google'; + this._userProfileURL = options.userProfileURL || 'https://www.googleapis.com/plus/v1/people/me'; + + var url = uri.parse(this._userProfileURL); + if (url.pathname.indexOf('/userinfo') == (url.pathname.length - '/userinfo'.length)) { + this._userProfileFormat = 'openid'; + } else { + this._userProfileFormat = 'google+'; // Google Sign-In + } +} + +// Inherit from `OAuth2Strategy`. +util.inherits(Strategy, OAuth2Strategy); + + +/** + * Retrieve user profile from Google. + * + * This function constructs a normalized profile, with the following properties: + * + * - `provider` always set to `google` + * - `id` + * - `username` + * - `displayName` + * + * @param {string} accessToken + * @param {function} done + * @access protected + */ +Strategy.prototype.userProfile = function(accessToken, done) { + var self = this; + this._oauth2.get(this._userProfileURL, accessToken, function (err, body, res) { + var json; + + if (err) { + if (err.data) { + try { + json = JSON.parse(err.data); + } catch (_) {} + } + + if (json && json.error && json.error.message) { + return done(new GooglePlusAPIError(json.error.message, json.error.code)); + } else if (json && json.error && json.error_description) { + return done(new UserInfoError(json.error_description, json.error)); + } + return done(new InternalOAuthError('Failed to fetch user profile', err)); + } + + try { + json = JSON.parse(body); + } catch (ex) { + return done(new Error('Failed to parse user profile')); + } + + var profile; + switch (self._userProfileFormat) { + case 'openid': + profile = OpenIDProfile.parse(json); + break; + default: // Google Sign-In + profile = GooglePlusProfile.parse(json); + break; + } + + profile.provider = 'google'; + profile._raw = body; + profile._json = json; + + done(null, profile); + }); +} + +/** + * Return extra Google-specific parameters to be included in the authorization + * request. + * + * @param {object} options + * @return {object} + * @access protected + */ +Strategy.prototype.authorizationParams = function(options) { + var params = {}; + + // https://developers.google.com/identity/protocols/OAuth2WebServer + if (options.accessType) { + params['access_type'] = options.accessType; + } + if (options.prompt) { + params['prompt'] = options.prompt; + } + if (options.loginHint) { + params['login_hint'] = options.loginHint; + } + if (options.includeGrantedScopes) { + params['include_granted_scopes'] = true; + } + + // https://developers.google.com/identity/protocols/OpenIDConnect + if (options.display) { + // Specify what kind of display consent screen to display to users. + // https://developers.google.com/accounts/docs/OpenIDConnect#authenticationuriparameters + params['display'] = options.display; + } + + // Google Apps for Work + if (options.hostedDomain || options.hd) { + // This parameter is derived from Google's OAuth 1.0 endpoint, and (although + // undocumented) is supported by Google's OAuth 2.0 endpoint was well. + // https://developers.google.com/accounts/docs/OAuth_ref + params['hd'] = options.hostedDomain || options.hd; + } + + // Google+ + if (options.requestVisibleActions) { + // Space separated list of allowed app actions + // as documented at: + // https://developers.google.com/+/web/app-activities/#writing_an_app_activity_using_the_google_apis_client_libraries + // https://developers.google.com/+/api/moment-types/ + params['request_visible_actions'] = options.requestVisibleActions; + } + + // OpenID 2.0 migration + if (options.openIDRealm) { + // This parameter is needed when migrating users from Google's OpenID 2.0 to OAuth 2.0 + // https://developers.google.com/accounts/docs/OpenID?hl=ja#adjust-uri + params['openid.realm'] = options.openIDRealm; + } + + // Undocumented + if (options.approvalPrompt) { + params['approval_prompt'] = options.approvalPrompt; + } + if (options.userID) { + // Undocumented, but supported by Google's OAuth 2.0 endpoint. Appears to + // be equivalent to `login_hint`. + params['user_id'] = options.userID; + } + + return params; +} + + +/** + * Expose `Strategy`. + */ +module.exports = Strategy; |
