Merge pull request #463 from coralproject/facebook-auth-plugin

Facebook Auth Plugin
This commit is contained in:
David Erwin
2017-04-05 15:31:53 -04:00
committed by GitHub
15 changed files with 155 additions and 88 deletions
+3 -2
View File
@@ -1,5 +1,6 @@
dist
client/lib
**/*.html
plugins/
plugins/**/node_modules
plugins/*
!plugins/coral-plugin-facebook-auth
node_modules
+11 -5
View File
@@ -1,12 +1,18 @@
node_modules
npm-debug.log*
dist
test/e2e/reports
npm-debug.log*
dump.rdb
.env
*.cfg
.idea/
coverage/
*.swp
plugins
plugins.json
test/e2e/reports
coverage/
plugins/*
!plugins/coral-plugin-facebook-auth
-6
View File
@@ -28,12 +28,6 @@ The Talk application looks for the following configuration values either as envi
secure cookies.
- `TALK_ROOT_URL` (*required*) - root url of the installed application externally
available in the format: `<scheme>://<host>` without the path.
- `TALK_FACEBOOK_APP_ID` (*required for login via fb*) - the Facebook app id for your Facebook
Login enabled app.
- `TALK_FACEBOOK_APP_SECRET` (*required for login via fb*) - the Facebook app secret for your
Facebook Login enabled app.
- `TALK_SMTP_EMAIL` (*required for email*) - the address to send emails from using the
SMTP provider.
- `TALK_SMTP_USERNAME` (*required for email*) - username of the SMTP provider you are using.
+12
View File
@@ -4,6 +4,7 @@ const morgan = require('morgan');
const path = require('path');
const helmet = require('helmet');
const {passport} = require('./services/passport');
const plugins = require('./services/plugins');
const session = require('express-session');
const enabled = require('debug').enabled;
const RedisStore = require('connect-redis')(session);
@@ -75,6 +76,17 @@ app.use(session(session_opts));
// PASSPORT MIDDLEWARE
//==============================================================================
const passportDebug = require('debug')('talk:passport');
// Install the passport plugins.
plugins.get('server', 'passport').forEach((plugin) => {
passportDebug(`added plugin '${plugin.plugin.name}'`);
// Pass the passport.js instance to the plugin to allow it to inject it's
// functionality.
plugin.passport(passport);
});
// Setup the PassportJS Middleware.
app.use(passport.initialize());
app.use(passport.session());
+1 -1
View File
@@ -4,6 +4,7 @@
"description": "A commenting platform from The Coral Project. https://coralproject.net",
"main": "app.js",
"scripts": {
"postinstall": "./bin/cli plugins reconcile --skip-remote",
"start": "./bin/cli serve --jobs",
"dev-start": "nodemon --config .nodemon.json --exec \"./bin/cli -c .env serve --jobs\"",
"build": "NODE_ENV=production webpack --progress -p --config webpack.config.js --bail",
@@ -88,7 +89,6 @@
"nodemailer": "^2.6.4",
"parse-duration": "^0.1.1",
"passport": "^0.3.2",
"passport-facebook": "^2.1.1",
"passport-local": "^1.0.0",
"react-apollo": "^0.10.0",
"react-recaptcha": "^2.2.6",
+5
View File
@@ -0,0 +1,5 @@
{
"server": [
"coral-plugin-facebook-auth"
]
}
@@ -0,0 +1,24 @@
# coral-plugin-facebook-auth
This plugin provides facebook authentication support for Talk.
## Configuration
This plugin looks for the following configuration from the environment:
- `TALK_FACEBOOK_APP_ID` (*required*) - the Facebook app id for your Facebook
Login enabled app.
- `TALK_FACEBOOK_APP_SECRET` (*required*) - the Facebook app secret for your
Facebook Login enabled app.
### License
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and limitations under the License.
@@ -0,0 +1,7 @@
const passport = require('./server/passport');
const router = require('./server/router');
module.exports = {
passport,
router
};
@@ -0,0 +1,9 @@
{
"name": "coral-plugin-facebook-auth",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"passport-facebook": "^2.1.1"
}
}
@@ -0,0 +1,27 @@
const FacebookStrategy = require('passport-facebook').Strategy;
const UsersService = require('services/users');
const {ValidateUserLogin} = require('services/passport');
module.exports = (passport) => {
if (process.env.TALK_FACEBOOK_APP_ID && process.env.TALK_FACEBOOK_APP_SECRET && process.env.TALK_ROOT_URL) {
passport.use(new FacebookStrategy({
clientID: process.env.TALK_FACEBOOK_APP_ID,
clientSecret: process.env.TALK_FACEBOOK_APP_SECRET,
callbackURL: `${process.env.TALK_ROOT_URL}/api/v1/auth/facebook/callback`,
passReqToCallback: true,
profileFields: ['id', 'displayName', 'picture.type(large)']
}, async (req, accessToken, refreshToken, profile, done) => {
let user;
try {
user = await UsersService.findOrCreateExternalUser(profile);
} catch (err) {
return done(err);
}
return ValidateUserLogin(profile, user, done);
}));
} else if (process.env.NODE_ENV !== 'test') {
throw new Error('Facebook cannot be enabled, missing one of TALK_FACEBOOK_APP_ID, TALK_FACEBOOK_APP_SECRET, TALK_ROOT_URL');
}
};
@@ -0,0 +1,20 @@
module.exports = (router) => {
const {passport, HandleAuthPopupCallback} = require('services/passport');
/**
* Facebook auth endpoint, this will redirect the user immediatly to facebook
* for authorization.
*/
router.get('/api/v1/auth/facebook', passport.authenticate('facebook', {display: 'popup', authType: 'rerequest', scope: ['public_profile']}));
/**
* Facebook callback endpoint, this will send the user a html page designed to
* send back the user credentials upon sucesfull login.
*/
router.get('/api/v1/auth/facebook/callback', (req, res, next) => {
// Perform the facebook login flow and pass the data back through the opener.
passport.authenticate('facebook', HandleAuthPopupCallback(req, res, next))(req, res, next);
});
};
@@ -0,0 +1,34 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
oauth@0.9.x:
version "0.9.15"
resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
passport-facebook@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/passport-facebook/-/passport-facebook-2.1.1.tgz#c39d0b52ae4d59163245a4e21a7b9b6321303311"
dependencies:
passport-oauth2 "1.x.x"
passport-oauth2@1.x.x:
version "1.4.0"
resolved "https://registry.yarnpkg.com/passport-oauth2/-/passport-oauth2-1.4.0.tgz#f62f81583cbe12609be7ce6f160b9395a27b86ad"
dependencies:
oauth "0.9.x"
passport-strategy "1.x.x"
uid2 "0.0.x"
utils-merge "1.x.x"
passport-strategy@1.x.x:
version "1.0.0"
resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4"
uid2@0.0.x:
version "0.0.3"
resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.3.tgz#483126e11774df2f71b8b639dcd799c376162b82"
utils-merge@1.x.x:
version "1.0.0"
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8"
+1 -17
View File
@@ -1,5 +1,5 @@
const express = require('express');
const {passport, HandleAuthCallback, HandleAuthPopupCallback} = require('../../../services/passport');
const {passport, HandleAuthCallback} = require('../../../services/passport');
const authorization = require('../../../middleware/authorization');
const router = express.Router();
@@ -42,20 +42,4 @@ router.post('/local', (req, res, next) => {
passport.authenticate('local', HandleAuthCallback(req, res, next))(req, res, next);
});
/**
* Facebook auth endpoint, this will redirect the user immediatly to facebook
* for authorization.
*/
router.get('/facebook', passport.authenticate('facebook', {display: 'popup', authType: 'rerequest', scope: ['public_profile']}));
/**
* Facebook callback endpoint, this will send the user a html page designed to
* send back the user credentials upon sucesfull login.
*/
router.get('/facebook/callback', (req, res, next) => {
// Perform the facebook login flow and pass the data back through the opener.
passport.authenticate('facebook', HandleAuthPopupCallback(req, res, next))(req, res, next);
});
module.exports = router;
-33
View File
@@ -4,10 +4,8 @@ const SettingsService = require('./settings');
const fetch = require('node-fetch');
const FormData = require('form-data');
const LocalStrategy = require('passport-local').Strategy;
const FacebookStrategy = require('passport-facebook').Strategy;
const errors = require('../errors');
const debug = require('debug')('talk:passport');
const plugins = require('./plugins');
//==============================================================================
// SESSION SERIALIZATION
@@ -354,37 +352,6 @@ passport.use(new LocalStrategy({
return ValidateUserLogin(loginProfile, user, done);
}));
if (process.env.TALK_FACEBOOK_APP_ID && process.env.TALK_FACEBOOK_APP_SECRET && process.env.TALK_ROOT_URL) {
passport.use(new FacebookStrategy({
clientID: process.env.TALK_FACEBOOK_APP_ID,
clientSecret: process.env.TALK_FACEBOOK_APP_SECRET,
callbackURL: `${process.env.TALK_ROOT_URL}/api/v1/auth/facebook/callback`,
passReqToCallback: true,
profileFields: ['id', 'displayName', 'picture.type(large)']
}, async (req, accessToken, refreshToken, profile, done) => {
let user;
try {
user = await UsersService.findOrCreateExternalUser(profile);
} catch (err) {
return done(err);
}
return ValidateUserLogin(profile, user, done);
}));
} else {
console.error('Facebook cannot be enabled, missing one of TALK_FACEBOOK_APP_ID, TALK_FACEBOOK_APP_SECRET, TALK_ROOT_URL');
}
// Inject server route plugins.
plugins.get('server', 'passport').forEach((plugin) => {
debug(`added plugin '${plugin.plugin.name}'`);
// Pass the passport.js instance to the plugin to allow it to inject it's
// functionality.
plugin.passport(passport);
});
module.exports = {
passport,
ValidateUserLogin,
+1 -24
View File
@@ -5372,10 +5372,6 @@ oauth-sign@~0.8.1:
version "0.8.2"
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
oauth@0.9.x:
version "0.9.15"
resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
object-assign@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2"
@@ -5589,27 +5585,12 @@ parseurl@~1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.1.tgz#c8ab8c9223ba34888aa64a297b28853bec18da56"
passport-facebook@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/passport-facebook/-/passport-facebook-2.1.1.tgz#c39d0b52ae4d59163245a4e21a7b9b6321303311"
dependencies:
passport-oauth2 "1.x.x"
passport-local@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/passport-local/-/passport-local-1.0.0.tgz#1fe63268c92e75606626437e3b906662c15ba6ee"
dependencies:
passport-strategy "1.x.x"
passport-oauth2@1.x.x:
version "1.4.0"
resolved "https://registry.yarnpkg.com/passport-oauth2/-/passport-oauth2-1.4.0.tgz#f62f81583cbe12609be7ce6f160b9395a27b86ad"
dependencies:
oauth "0.9.x"
passport-strategy "1.x.x"
uid2 "0.0.x"
utils-merge "1.x.x"
passport-strategy@1.x.x:
version "1.0.0"
resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4"
@@ -7782,10 +7763,6 @@ uid-safe@2.1.3, uid-safe@~2.1.3:
base64-url "1.3.3"
random-bytes "~1.0.0"
uid2@0.0.x:
version "0.0.3"
resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.3.tgz#483126e11774df2f71b8b639dcd799c376162b82"
undefsafe@0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-0.0.3.tgz#ecca3a03e56b9af17385baac812ac83b994a962f"
@@ -7855,7 +7832,7 @@ util@0.10.3, util@^0.10.3:
dependencies:
inherits "2.0.1"
utils-merge@1.0.0, utils-merge@1.x.x:
utils-merge@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8"