Added support for auth based plugins

This commit is contained in:
Wyatt Johnson
2017-04-03 16:06:38 -06:00
parent c5098a3e91
commit 8d3524dd61
4 changed files with 117 additions and 51 deletions
+52
View File
@@ -233,6 +233,58 @@ module.exports = {
}
```
#### Field: `auth`
```js
const FacebookStrategy = require('passport-facebook').Strategy;
const UsersService = require('services/users');
const {ValidateUserLogin, HandleAuthPopupCallback} = require('services/passport');
module.exports = {
auth(passport) {
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);
}));
},
routes(router) {
const {passport} = require('services/passport');
/**
* 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);
});
}
};
```
This is a full example including the routes hook to add the required components
to the application router to support a different auth strategy.
### Full Example
Contents of `plugins.json`:
+1 -1
View File
@@ -3,7 +3,7 @@ const bodyParser = require('body-parser');
const morgan = require('morgan');
const path = require('path');
const helmet = require('helmet');
const passport = require('./services/passport');
const {passport} = require('./services/passport');
const session = require('express-session');
const enabled = require('debug').enabled;
const RedisStore = require('connect-redis')(session);
+1 -49
View File
@@ -1,7 +1,6 @@
const express = require('express');
const passport = require('../../../services/passport');
const {passport, HandleAuthCallback, HandleAuthPopupCallback} = require('../../../services/passport');
const authorization = require('../../../middleware/authorization');
const errors = require('../../../errors');
const router = express.Router();
@@ -34,53 +33,6 @@ router.delete('/', authorization.needed(), (req, res) => {
// PASSPORT ROUTES
//==============================================================================
/**
* This sends back the user data as JSON.
*/
const HandleAuthCallback = (req, res, next) => (err, user) => {
if (err) {
return next(err);
}
if (!user) {
return next(errors.ErrNotAuthorized);
}
// Perform the login of the user!
req.logIn(user, (err) => {
if (err) {
return next(err);
}
// We logged in the user! Let's send back the user data and the CSRF token.
res.json({user});
});
};
/**
* Returns the response to the login attempt via a popup callback with some JS.
*/
const HandleAuthPopupCallback = (req, res, next) => (err, user) => {
if (err) {
return res.render('auth-callback', {err: JSON.stringify(err), data: null});
}
if (!user) {
return res.render('auth-callback', {err: JSON.stringify(errors.ErrNotAuthorized), data: null});
}
// Perform the login of the user!
req.logIn(user, (err) => {
if (err) {
return res.render('auth-callback', {err: JSON.stringify(err), data: null});
}
// We logged in the user! Let's send back the user data.
res.render('auth-callback', {err: null, data: JSON.stringify(user)});
});
};
/**
* Local auth endpoint, will recieve a email and password
*/
+63 -1
View File
@@ -7,6 +7,7 @@ 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
@@ -27,6 +28,52 @@ passport.deserializeUser((id, done) => {
});
});
/**
* This sends back the user data as JSON.
*/
const HandleAuthCallback = (req, res, next) => (err, user) => {
if (err) {
return next(err);
}
if (!user) {
return next(errors.ErrNotAuthorized);
}
// Perform the login of the user!
req.logIn(user, (err) => {
if (err) {
return next(err);
}
// We logged in the user! Let's send back the user data and the CSRF token.
res.json({user});
});
};
/**
* Returns the response to the login attempt via a popup callback with some JS.
*/
const HandleAuthPopupCallback = (req, res, next) => (err, user) => {
if (err) {
return res.render('auth-callback', {err: JSON.stringify(err), data: null});
}
if (!user) {
return res.render('auth-callback', {err: JSON.stringify(errors.ErrNotAuthorized), data: null});
}
// Perform the login of the user!
req.logIn(user, (err) => {
if (err) {
return res.render('auth-callback', {err: JSON.stringify(err), data: null});
}
// We logged in the user! Let's send back the user data.
res.render('auth-callback', {err: null, data: JSON.stringify(user)});
});
};
/**
* Validates that a user is allowed to login.
* @param {User} user the user to be validated
@@ -329,4 +376,19 @@ if (process.env.TALK_FACEBOOK_APP_ID && process.env.TALK_FACEBOOK_APP_SECRET &&
console.error('Facebook cannot be enabled, missing one of TALK_FACEBOOK_APP_ID, TALK_FACEBOOK_APP_SECRET, TALK_ROOT_URL');
}
module.exports = passport;
// Inject server route plugins.
plugins.get('server', 'auth').forEach(({plugin, auth}) => {
debug(`added plugin '${plugin.name}'`);
// Pass the passport.js instance to the plugin to allow it to inject it's
// functionality.
auth(passport);
});
module.exports = {
passport,
ValidateUserLogin,
HandleFailedAttempt,
HandleAuthCallback,
HandleAuthPopupCallback
};