@passport-next/passport-facebook
Advanced tools
Comparing version 3.0.0 to 3.1.0
@@ -0,10 +1,29 @@ | ||
This changelog follows Semantic Versioning https://semver.org/ | ||
# 3.1.0 (2019-01-22) | ||
### Minor | ||
* Check that graphApiToken matches required format #4 @rwky | ||
* Linted via ESLint @rwky | ||
### Patch | ||
* Added gitlab SAST @rwky | ||
* Updated dev deps @rwky | ||
# 3.0.0 (2018-08-07) | ||
### Major | ||
* Made graphApiVersion a mandatory option @rwky | ||
* Added tests using the live facebook graph api @rwky | ||
* Removed deprecated username field @rwky | ||
* Fixed birthday field not populating @rwky | ||
### Minor | ||
* Set displayName to name field @rwky | ||
### Patch | ||
* README.md updates @rwky | ||
* Updated deps @rwky | ||
* Added tests using the live facebook graph api @rwky | ||
* Fixed birthday field not populating @rwky | ||
@@ -11,0 +30,0 @@ # 2.5.0 (2018-07-07) |
@@ -18,3 +18,3 @@ /** | ||
Error.call(this); | ||
Error.captureStackTrace(this, arguments.callee); | ||
Error.captureStackTrace(this, FacebookAuthorizationError); | ||
this.name = 'FacebookAuthorizationError'; | ||
@@ -26,7 +26,3 @@ this.message = message; | ||
// Inherit from `Error`. | ||
FacebookAuthorizationError.prototype.__proto__ = Error.prototype; | ||
// Expose constructor. | ||
module.exports = FacebookAuthorizationError; |
@@ -17,3 +17,3 @@ /** | ||
Error.call(this); | ||
Error.captureStackTrace(this, arguments.callee); | ||
Error.captureStackTrace(this, FacebookGraphAPIError); | ||
this.name = 'FacebookGraphAPIError'; | ||
@@ -28,7 +28,3 @@ this.message = message; | ||
// Inherit from `Error`. | ||
FacebookGraphAPIError.prototype.__proto__ = Error.prototype; | ||
// Expose constructor. | ||
module.exports = FacebookGraphAPIError; |
@@ -21,3 +21,3 @@ /** | ||
Error.call(this); | ||
Error.captureStackTrace(this, arguments.callee); | ||
Error.captureStackTrace(this, FacebookTokenError); | ||
this.name = 'FacebookTokenError'; | ||
@@ -32,7 +32,3 @@ this.message = message; | ||
// Inherit from `Error`. | ||
FacebookTokenError.prototype.__proto__ = Error.prototype; | ||
// Expose constructor. | ||
module.exports = FacebookTokenError; |
// Load modules. | ||
var Strategy = require('./strategy'); | ||
const Strategy = require('./strategy'); | ||
Strategy.Strategy = Strategy; | ||
// Expose Strategy. | ||
exports = module.exports = Strategy; | ||
// Exports. | ||
exports.Strategy = Strategy; | ||
module.exports = Strategy; |
@@ -8,16 +8,18 @@ /** | ||
*/ | ||
exports.parse = function(json) { | ||
if ('string' == typeof json) { | ||
exports.parse = function parse(json) { | ||
if (typeof json === 'string') { | ||
json = JSON.parse(json); | ||
} | ||
var profile = {}; | ||
const profile = {}; | ||
profile.id = json.id; | ||
profile.username = json.username; | ||
profile.displayName = json.name; | ||
profile.name = { familyName: json.last_name, | ||
givenName: json.first_name, | ||
middleName: json.middle_name }; | ||
profile.name = { | ||
familyName: json.last_name, | ||
givenName: json.first_name, | ||
middleName: json.middle_name | ||
}; | ||
if (typeof profile.displayName === 'undefined') { | ||
profile.displayName = json.first_name + ' ' + json.middle_name + ' ' + json.last_name; | ||
profile.displayName = `${json.first_name} ${json.middle_name} ${json.last_name}`; | ||
} | ||
@@ -29,9 +31,9 @@ | ||
profile.birthday = json.birthday; | ||
if (json.email) { | ||
profile.emails = [{ value: json.email }]; | ||
} | ||
if (json.picture) { | ||
if (typeof json.picture == 'object' && json.picture.data) { | ||
if (typeof json.picture === 'object' && json.picture.data) { | ||
// October 2012 Breaking Changes | ||
@@ -43,4 +45,4 @@ profile.photos = [{ value: json.picture.data.url }]; | ||
} | ||
return profile; | ||
}; |
// Load modules. | ||
var OAuth2Strategy = require('@passport-next/passport-oauth2') | ||
, util = require('util') | ||
, uri = require('url') | ||
, crypto = require('crypto') | ||
, Profile = require('./profile') | ||
, InternalOAuthError = require('@passport-next/passport-oauth2').InternalOAuthError | ||
, FacebookAuthorizationError = require('./errors/facebookauthorizationerror') | ||
, FacebookTokenError = require('./errors/facebooktokenerror') | ||
, FacebookGraphAPIError = require('./errors/facebookgraphapierror'); | ||
const OAuth2Strategy = require('@passport-next/passport-oauth2'); | ||
const util = require('util'); | ||
const uri = require('url'); | ||
const crypto = require('crypto'); | ||
const InternalOAuthError = require('@passport-next/passport-oauth2').InternalOAuthError; | ||
const Profile = require('./profile'); | ||
const FacebookAuthorizationError = require('./errors/facebookauthorizationerror'); | ||
const FacebookTokenError = require('./errors/facebooktokenerror'); | ||
const FacebookGraphAPIError = require('./errors/facebookgraphapierror'); | ||
/** | ||
@@ -50,8 +63,11 @@ * `Strategy` constructor. | ||
options = options || {}; | ||
var graphApiVersion = options.graphApiVersion; | ||
const graphApiVersion = options.graphApiVersion; | ||
if (!graphApiVersion) { | ||
throw new Error('graphApiVersion is required'); | ||
} | ||
options.authorizationURL = options.authorizationURL || 'https://www.facebook.com/' + graphApiVersion + '/dialog/oauth'; | ||
options.tokenURL = options.tokenURL || 'https://graph.facebook.com/' + graphApiVersion + '/oauth/access_token'; | ||
if (!/^v[0-9]{1}\.[0-9]{1,2}/.test(graphApiVersion)) { | ||
throw new Error('Invalid graphApiVersion it must be in the format "vX.YY"'); | ||
} | ||
options.authorizationURL = options.authorizationURL || `https://www.facebook.com/${graphApiVersion}/dialog/oauth`; | ||
options.tokenURL = options.tokenURL || `https://graph.facebook.com/${graphApiVersion}/oauth/access_token`; | ||
options.scopeSeparator = options.scopeSeparator || ','; | ||
@@ -61,3 +77,3 @@ | ||
this.name = 'facebook'; | ||
this._profileURL = options.profileURL || 'https://graph.facebook.com/' + graphApiVersion + '/me'; | ||
this._profileURL = options.profileURL || `https://graph.facebook.com/${graphApiVersion}/me`; | ||
this._profileFields = options.profileFields || null; | ||
@@ -79,3 +95,3 @@ this._enableProof = options.enableProof; | ||
*/ | ||
Strategy.prototype.authenticate = function(req, options) { | ||
Strategy.prototype.authenticate = function authenticate(req, options) { | ||
// Facebook doesn't conform to the OAuth 2.0 specification, with respect to | ||
@@ -86,6 +102,7 @@ // redirecting with error codes. | ||
if (req.query && req.query.error_code && !req.query.error) { | ||
return this.error(new FacebookAuthorizationError(req.query.error_message, parseInt(req.query.error_code, 10))); | ||
return this.error(new FacebookAuthorizationError(req.query.error_message, | ||
parseInt(req.query.error_code, 10))); | ||
} | ||
OAuth2Strategy.prototype.authenticate.call(this, req, options); | ||
return OAuth2Strategy.prototype.authenticate.call(this, req, options); | ||
}; | ||
@@ -104,4 +121,4 @@ | ||
*/ | ||
Strategy.prototype.authorizationParams = function (options) { | ||
var params = {}; | ||
Strategy.prototype.authorizationParams = function authorizationParams(options) { | ||
const params = {}; | ||
@@ -143,4 +160,4 @@ // https://developers.facebook.com/docs/reference/dialogs/oauth/ | ||
*/ | ||
Strategy.prototype.userProfile = function(accessToken, done) { | ||
var url = uri.parse(this._profileURL); | ||
Strategy.prototype.userProfile = function userProfile(accessToken, done) { | ||
let url = uri.parse(this._profileURL); | ||
if (this._enableProof) { | ||
@@ -154,13 +171,13 @@ // Secure API call by adding proof of the app secret. This is required when | ||
// https://developers.facebook.com/docs/reference/api/securing-graph-api/ | ||
var proof = crypto.createHmac('sha256', this._clientSecret).update(accessToken).digest('hex'); | ||
url.search = (url.search ? url.search + '&' : '') + 'appsecret_proof=' + proof; | ||
const proof = crypto.createHmac('sha256', this._clientSecret).update(accessToken).digest('hex'); | ||
url.search = `${url.search ? `${url.search}&` : ''}appsecret_proof=${proof}`; | ||
} | ||
if (this._profileFields) { | ||
var fields = this._convertProfileFields(this._profileFields); | ||
if (fields !== '') { url.search = (url.search ? url.search + '&' : '') + 'fields=' + fields; } | ||
const fields = this._convertProfileFields(this._profileFields); | ||
if (fields !== '') { url.search = `${url.search ? `${url.search}&` : ''}fields=${fields}`; } | ||
} | ||
url = uri.format(url); | ||
this._oauth2.get(url, accessToken, function (err, body, res) { | ||
var json; | ||
this._oauth2.get(url, accessToken, (err, body) => { | ||
let json; | ||
@@ -171,7 +188,10 @@ if (err) { | ||
json = JSON.parse(err.data); | ||
} catch (_) {} | ||
} catch (_) { | ||
json = {}; | ||
} | ||
} | ||
if (json && json.error && typeof json.error == 'object') { | ||
return done(new FacebookGraphAPIError(json.error.message, json.error.type, json.error.code, json.error.error_subcode, json.error.fbtrace_id)); | ||
if (json && json.error && typeof json.error === 'object') { | ||
return done(new FacebookGraphAPIError(json.error.message, json.error.type, | ||
json.error.code, json.error.error_subcode, json.error.fbtrace_id)); | ||
} | ||
@@ -187,3 +207,3 @@ return done(new InternalOAuthError('Failed to fetch user profile', err)); | ||
var profile = Profile.parse(json); | ||
const profile = Profile.parse(json); | ||
profile.provider = 'facebook'; | ||
@@ -193,3 +213,3 @@ profile._raw = body; | ||
done(null, profile); | ||
return done(null, profile); | ||
}); | ||
@@ -206,6 +226,7 @@ }; | ||
*/ | ||
Strategy.prototype.parseErrorResponse = function(body, status) { | ||
var json = JSON.parse(body); | ||
if (json.error && typeof json.error == 'object') { | ||
return new FacebookTokenError(json.error.message, json.error.type, json.error.code, json.error.error_subcode, json.error.fbtrace_id); | ||
Strategy.prototype.parseErrorResponse = function parseErrorResponse(body, status) { | ||
const json = JSON.parse(body); | ||
if (json.error && typeof json.error === 'object') { | ||
return new FacebookTokenError(json.error.message, json.error.type, | ||
json.error.code, json.error.error_subcode, json.error.fbtrace_id); | ||
} | ||
@@ -222,23 +243,24 @@ return OAuth2Strategy.prototype.parseErrorResponse.call(this, body, status); | ||
*/ | ||
Strategy.prototype._convertProfileFields = function(profileFields) { | ||
var map = { | ||
'id': 'id', | ||
'displayName': 'name', | ||
'name': ['last_name', 'first_name', 'middle_name'], | ||
'gender': 'gender', | ||
'birthday': 'birthday', | ||
'profileUrl': 'link', | ||
'emails': 'email', | ||
'photos': 'picture', | ||
'ageRange': 'age_range', | ||
'currentLocation': 'location', | ||
'hometown': 'hometown' | ||
Strategy.prototype._convertProfileFields = function _convertProfileFields(profileFields) { | ||
const map = { | ||
id: 'id', | ||
displayName: 'name', | ||
name: ['last_name', 'first_name', 'middle_name'], | ||
gender: 'gender', | ||
birthday: 'birthday', | ||
profileUrl: 'link', | ||
emails: 'email', | ||
photos: 'picture', | ||
ageRange: 'age_range', | ||
currentLocation: 'location', | ||
hometown: 'hometown' | ||
}; | ||
var fields = []; | ||
const fields = []; | ||
profileFields.forEach(function(f) { | ||
// eslint-disable-next-line consistent-return | ||
profileFields.forEach((f) => { | ||
// return raw Facebook profile field to support the many fields that don't | ||
// map cleanly to Portable Contacts | ||
if (typeof map[f] === 'undefined') { return fields.push(f); }; | ||
if (typeof map[f] === 'undefined') { return fields.push(f); } | ||
@@ -245,0 +267,0 @@ if (Array.isArray(map[f])) { |
{ | ||
"name": "@passport-next/passport-facebook", | ||
"version": "3.0.0", | ||
"version": "3.1.0", | ||
"description": "Facebook authentication strategy for Passport.", | ||
@@ -36,6 +36,9 @@ "keywords": [ | ||
"devDependencies": { | ||
"@passport-next/chai-passport-strategy": "1.1.x", | ||
"chai": "^4.2.0", | ||
"make-node": "0.3.x", | ||
"mocha": "5.x.x", | ||
"chai": "4.x.x", | ||
"@passport-next/chai-passport-strategy": "1.1.x" | ||
"eslint-config-airbnb-base": "13.1.x", | ||
"eslint-plugin-import": "2.15.x", | ||
"eslint": "5.12.x" | ||
}, | ||
@@ -46,4 +49,7 @@ "engines": { | ||
"scripts": { | ||
"test": "node_modules/.bin/mocha --require test/bootstrap/node test/*.test.js" | ||
"spec": "node_modules/.bin/mocha --require test/bootstrap/node test/*.test.js", | ||
"lint": "eslint --ext .js . --max-warnings 0", | ||
"lintfix": "eslint --ext .js . --fix", | ||
"test": "npm run lint && npm run spec" | ||
} | ||
} |
@@ -8,3 +8,3 @@ # passport-facebook | ||
[![Dependencies](https://david-dm.org/passport-next/passport-facebook.png)](https://david-dm.org/passport-next/passport-facebook) | ||
<!--[![SAST](https://gitlab.com/passport-next/passport-facebook/badges/master/build.svg)](https://gitlab.com/passport-next/passport-facebook/badges/master/build.svg)--> | ||
[![SAST](https://gitlab.com/passport-next/passport-facebook/badges/master/build.svg)](https://gitlab.com/passport-next/passport-facebook/badges/master/build.svg) | ||
@@ -50,3 +50,4 @@ | ||
clientSecret: FACEBOOK_APP_SECRET, | ||
callbackURL: "http://localhost:3000/auth/facebook/callback" | ||
callbackURL: 'http://localhost:3000/auth/facebook/callback', | ||
graphApiVersion: 'v3.2' | ||
}, | ||
@@ -128,3 +129,4 @@ function(accessToken, refreshToken, profile, cb) { | ||
clientSecret: FACEBOOK_APP_SECRET, | ||
callbackURL: "http://localhost:3000/auth/facebook/callback", | ||
callbackURL: 'http://localhost:3000/auth/facebook/callback', | ||
graphApiVersion: 'v3.2', | ||
profileFields: ['id', 'displayName', 'photos', 'email'] | ||
@@ -145,3 +147,4 @@ }), ...) | ||
clientSecret: FACEBOOK_APP_SECRET, | ||
callbackURL: "http://localhost:3000/auth/facebook/callback", | ||
callbackURL: 'http://localhost:3000/auth/facebook/callback', | ||
graphApiVersion: 'v3.2', | ||
enableProof: true | ||
@@ -174,4 +177,4 @@ }, ...) | ||
clientSecret: FACEBOOK_APP_SECRET, | ||
callbackURL: "http://localhost:3000/auth/facebook/callback", | ||
graphApiVersion: 'v3.1' | ||
callbackURL: 'http://localhost:3000/auth/facebook/callback', | ||
graphApiVersion: 'v3.2' | ||
}, ...) | ||
@@ -178,0 +181,0 @@ ``` |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
24181
13
379
199
7