simplifying the plugin a bit for new users
This commit is contained in:
parent
f41afad49a
commit
08338c9467
191
library.js
191
library.js
@ -11,63 +11,46 @@
|
|||||||
nconf = module.parent.require('nconf'),
|
nconf = module.parent.require('nconf'),
|
||||||
winston = module.parent.require('winston'),
|
winston = module.parent.require('winston'),
|
||||||
async = module.parent.require('async'),
|
async = module.parent.require('async'),
|
||||||
passportOAuth;
|
|
||||||
|
|
||||||
var constants = Object.freeze({
|
constants = Object.freeze({
|
||||||
'name': "Generic OAuth",
|
type: '', // Either 'oauth' or 'oauth2'
|
||||||
'admin': {
|
name: '', // Something unique to your OAuth provider in lowercase, like "github", or "nodebb"
|
||||||
'route': '/plugins/sso-oauth',
|
oauth: {
|
||||||
'icon': 'fa-key'
|
requestTokenURL: '',
|
||||||
|
accessTokenURL: '',
|
||||||
|
userAuthorizationURL: '',
|
||||||
|
consumerKey: '',
|
||||||
|
consumerSecret: ''
|
||||||
|
},
|
||||||
|
oauth2: {
|
||||||
|
authorizationURL: '',
|
||||||
|
tokenURL: '',
|
||||||
|
clientID: '',
|
||||||
|
clientSecret: ''
|
||||||
}
|
}
|
||||||
});
|
}),
|
||||||
|
configOk = false,
|
||||||
|
OAuth = {}, passportOAuth;
|
||||||
|
|
||||||
var OAuth = {};
|
OAuth.init = function(app, middleware, controller, callback) {
|
||||||
|
if (!constants.name) {
|
||||||
OAuth.init = function(app, middleware, controllers, callback) {
|
winston.error('[sso-oauth] Please specify a name for your OAuth provider (library.js:17)');
|
||||||
function render(req, res, next) {
|
} else if (!constants.type || (constants.type !== 'oauth' && constants.type !== 'oauth2')) {
|
||||||
res.render('admin/plugins/sso-oauth', {});
|
winston.error('[sso-oauth] Please specify an OAuth strategy to utilise (library.js:16)');
|
||||||
|
} else {
|
||||||
|
configOk = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
app.get('/admin/plugins/sso-oauth', middleware.admin.buildHeader, render);
|
|
||||||
app.get('/api/admin/plugins/sso-oauth', render);
|
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
};
|
};
|
||||||
|
|
||||||
OAuth.getStrategy = function(strategies, callback) {
|
OAuth.getStrategy = function(strategies, callback) {
|
||||||
meta.settings.get('sso-oauth', function(err, settings) {
|
if (configOk) {
|
||||||
if (err) {
|
passportOAuth = require('passport-oauth')[constants.type === 'oauth' ? 'OAuthStrategy' : 'OAuth2Strategy'];
|
||||||
winston.error('[plugins/sso-oauth] Could not retrieve OAuth settings: ' + err.message);
|
|
||||||
} else if (!settings) {
|
|
||||||
settings = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
var oAuthKeys = ['oauth:reqTokenUrl', 'oauth:accessTokenUrl', 'oauth:authUrl', 'oauth:key', 'oauth:secret'],
|
if (constants.type === 'oauth') {
|
||||||
oAuth2Keys = ['oauth2:authUrl', 'oauth2:tokenUrl', 'oauth2:id', 'oauth2:secret'],
|
|
||||||
configOk = oAuthKeys.every(function(key) {
|
|
||||||
return settings[key];
|
|
||||||
}) || oAuth2Keys.every(function(key) {
|
|
||||||
return settings[key];
|
|
||||||
}),
|
|
||||||
opts;
|
|
||||||
|
|
||||||
if (settings['oauth:type'] === '2') {
|
|
||||||
passportOAuth = require('passport-oauth').OAuth2Strategy;
|
|
||||||
} else if (settings['oauth:type'] === '1') {
|
|
||||||
passportOAuth = require('passport-oauth').OAuthStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (passportOAuth && configOk) {
|
|
||||||
if (settings['oauth:type'] === '1') {
|
|
||||||
// OAuth options
|
// OAuth options
|
||||||
opts = {
|
opts = constants.oauth;
|
||||||
requestTokenURL: settings['oauth:reqTokenUrl'],
|
|
||||||
accessTokenURL: settings['oauth:accessTokenUrl'],
|
|
||||||
userAuthorizationURL: settings['oauth:authUrl'],
|
|
||||||
consumerKey: settings['oauth:key'],
|
|
||||||
consumerSecret: settings['oauth:secret'],
|
|
||||||
callbackURL: nconf.get('url') + '/auth/generic/callback'
|
|
||||||
};
|
|
||||||
|
|
||||||
passportOAuth.Strategy.prototype.userProfile = function(token, secret, params, done) {
|
passportOAuth.Strategy.prototype.userProfile = function(token, secret, params, done) {
|
||||||
this._oauth.get(settings['oauth:userProfileUrl'], token, secret, function(err, body, res) {
|
this._oauth.get(settings['oauth:userProfileUrl'], token, secret, function(err, body, res) {
|
||||||
@ -75,29 +58,18 @@
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
var json = JSON.parse(body);
|
var json = JSON.parse(body);
|
||||||
|
OAuth.parseUserReturn(body, function(err, profile) {
|
||||||
var profile = { provider: 'generic' };
|
profile.provider = constants.name
|
||||||
// Uncomment the following lines to include whatever data is necessary
|
});
|
||||||
// NodeBB requires the following: id, displayName, emails, e.g.:
|
|
||||||
// profile.id = json.id;
|
|
||||||
// profile.displayName = json.name;
|
|
||||||
// profile.emails = [{ value: json.email }];
|
|
||||||
|
|
||||||
done(null, profile);
|
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
done(e);
|
done(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
} else if (settings['oauth:type'] === '2') {
|
} else if (constants.type === 'oauth2') {
|
||||||
// OAuth 2 options
|
// OAuth 2 options
|
||||||
opts = {
|
opts = constants.settings.oauth2;
|
||||||
authorizationURL: settings['oauth2:authUrl'],
|
opts.callbackURL = nconf.get('url') + '/auth/' + constants.name + '/callback';
|
||||||
tokenURL: settings['oauth2:tokenUrl'],
|
|
||||||
clientID: settings['oauth2:id'],
|
|
||||||
clientSecret: settings['oauth2:secret'],
|
|
||||||
callbackURL: nconf.get('url') + '/auth/generic/callback'
|
|
||||||
};
|
|
||||||
|
|
||||||
passportOAuth.Strategy.prototype.userProfile = function(accessToken, done) {
|
passportOAuth.Strategy.prototype.userProfile = function(accessToken, done) {
|
||||||
this._oauth2.get(settings['oauth:userProfileUrl'], accessToken, function(err, body, res) {
|
this._oauth2.get(settings['oauth:userProfileUrl'], accessToken, function(err, body, res) {
|
||||||
@ -105,27 +77,9 @@
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
var json = JSON.parse(body);
|
var json = JSON.parse(body);
|
||||||
|
OAuth.parseUserReturn(body, function(err, profile) {
|
||||||
var profile = { provider: 'generic' };
|
profile.provider = constants.name
|
||||||
// Alter this section to include whatever data is necessary
|
});
|
||||||
// NodeBB *requires* the following: id, displayName, emails.
|
|
||||||
// Everything else is optional.
|
|
||||||
|
|
||||||
profile.id = json.id;
|
|
||||||
profile.displayName = json.name;
|
|
||||||
profile.emails = [{ value: json.email }];
|
|
||||||
|
|
||||||
// Do you want to automatically make somebody an admin? This block might help you do that...
|
|
||||||
// profile.isAdmin = json.isAdmin ? true : false;
|
|
||||||
|
|
||||||
// Find out what is available by uncommenting this line:
|
|
||||||
// console.log(json);
|
|
||||||
|
|
||||||
// Delete or comment out the next TWO (2) lines when you are ready to proceed
|
|
||||||
process.stdout.write('===\nAt this point, you\'ll need to customise the above section to id, displayName, and emails into the "profile" object.\n===');
|
|
||||||
return done(new Error('Congrats! So far so good -- please see server log for details'));
|
|
||||||
|
|
||||||
done(null, profile);
|
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
done(e);
|
done(e);
|
||||||
}
|
}
|
||||||
@ -133,7 +87,7 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
passport.use('Generic OAuth', new passportOAuth(opts, function(token, secret, profile, done) {
|
passport.use(constants.name, new passportOAuth(opts, function(token, secret, profile, done) {
|
||||||
OAuth.login({
|
OAuth.login({
|
||||||
oAuthid: profile.id,
|
oAuthid: profile.id,
|
||||||
handle: profile.displayName,
|
handle: profile.displayName,
|
||||||
@ -148,21 +102,42 @@
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
strategies.push({
|
strategies.push({
|
||||||
name: 'Generic OAuth',
|
name: constants.name,
|
||||||
url: '/auth/oauth',
|
url: '/auth/' + constants.name,
|
||||||
callbackURL: '/auth/generic/callback',
|
callbackURL: '/auth/' + constants.name + '/callback',
|
||||||
icon: 'check',
|
icon: 'check',
|
||||||
scope: (settings['oauth:scope'] || '').split(',')
|
scope: (constants.scope || '').split(',')
|
||||||
});
|
});
|
||||||
|
|
||||||
callback(null, strategies);
|
callback(null, strategies);
|
||||||
} else {
|
} else {
|
||||||
winston.info('[plugins/sso-oauth] OAuth Disabled or misconfigured. Proceeding without Generic OAuth Login');
|
callback(new Error('OAuth Configuration is invalid'));
|
||||||
callback(null, strategies);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
OAuth.parseUserReturn = function(data, callback) {
|
||||||
|
// Alter this section to include whatever data is necessary
|
||||||
|
// NodeBB *requires* the following: id, displayName, emails.
|
||||||
|
// Everything else is optional.
|
||||||
|
|
||||||
|
// Find out what is available by uncommenting this line:
|
||||||
|
// console.log(data);
|
||||||
|
|
||||||
|
var profile = {};
|
||||||
|
profile.id = data.id;
|
||||||
|
profile.displayName = data.name;
|
||||||
|
profile.emails = [{ value: data.email }];
|
||||||
|
|
||||||
|
// Do you want to automatically make somebody an admin? This line might help you do that...
|
||||||
|
// profile.isAdmin = data.isAdmin ? true : false;
|
||||||
|
|
||||||
|
// Delete or comment out the next TWO (2) lines when you are ready to proceed
|
||||||
|
process.stdout.write('===\nAt this point, you\'ll need to customise the above section to id, displayName, and emails into the "profile" object.\n===');
|
||||||
|
return done(new Error('Congrats! So far so good -- please see server log for details'));
|
||||||
|
|
||||||
|
done(null, profile);
|
||||||
|
}
|
||||||
|
|
||||||
OAuth.login = function(payload, callback) {
|
OAuth.login = function(payload, callback) {
|
||||||
OAuth.getUidByOAuthid(payload.oAuthid, function(err, uid) {
|
OAuth.getUidByOAuthid(payload.oAuthid, function(err, uid) {
|
||||||
if(err) {
|
if(err) {
|
||||||
@ -178,8 +153,8 @@
|
|||||||
// New User
|
// New User
|
||||||
var success = function(uid) {
|
var success = function(uid) {
|
||||||
// Save provider-specific information to the user
|
// Save provider-specific information to the user
|
||||||
User.setUserField(uid, 'oAuthid', payload.oAuthid);
|
User.setUserField(uid, constants.name + 'Id', payload.oAuthid);
|
||||||
db.setObjectField('oAuthid:uid', payload.oAuthid, uid);
|
db.setObjectField(constants.name + 'Id:uid', payload.oAuthid, uid);
|
||||||
|
|
||||||
if (payload.isAdmin) {
|
if (payload.isAdmin) {
|
||||||
Groups.join('administrators', uid, function(err) {
|
Groups.join('administrators', uid, function(err) {
|
||||||
@ -219,7 +194,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
OAuth.getUidByOAuthid = function(oAuthid, callback) {
|
OAuth.getUidByOAuthid = function(oAuthid, callback) {
|
||||||
db.getObjectField('oAuthid:uid', oAuthid, function(err, uid) {
|
db.getObjectField(constants.name + 'Id:uid', oAuthid, function(err, uid) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
@ -237,35 +212,15 @@
|
|||||||
callback(null, custom_header);
|
callback(null, custom_header);
|
||||||
};
|
};
|
||||||
|
|
||||||
OAuth.addAdminRoute = function(custom_routes, callback) {
|
|
||||||
fs.readFile(path.resolve(__dirname, './static/admin.tpl'), function (err, template) {
|
|
||||||
custom_routes.routes.push({
|
|
||||||
"route": constants.admin.route,
|
|
||||||
"method": "get",
|
|
||||||
"options": function(req, res, callback) {
|
|
||||||
callback({
|
|
||||||
req: req,
|
|
||||||
res: res,
|
|
||||||
route: constants.admin.route,
|
|
||||||
name: constants.name,
|
|
||||||
content: template
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
callback(null, custom_routes);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
OAuth.deleteUserData = function(uid, callback) {
|
OAuth.deleteUserData = function(uid, callback) {
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
async.apply(User.getUserField, uid, 'oAuthid'),
|
async.apply(User.getUserField, uid, constants.name + 'Id'),
|
||||||
function(oAuthIdToDelete, next) {
|
function(oAuthIdToDelete, next) {
|
||||||
db.deleteObjectField('oAuthid:uid', oAuthIdToDelete, next);
|
db.deleteObjectField(constants.name + 'Id:uid', oAuthIdToDelete, next);
|
||||||
}
|
}
|
||||||
], function(err) {
|
], function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
winston.error('Could not remove OAuthId data for uid ' + uid + '. Error: ' + err);
|
winston.error('[sso-oauth] Could not remove OAuthId data for uid ' + uid + '. Error: ' + err);
|
||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
callback();
|
callback();
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
"hooks": [
|
"hooks": [
|
||||||
{ "hook": "static:app.load", "method": "init" },
|
{ "hook": "static:app.load", "method": "init" },
|
||||||
{ "hook": "filter:user.delete", "method": "deleteUserData" },
|
{ "hook": "filter:user.delete", "method": "deleteUserData" },
|
||||||
{ "hook": "filter:auth.init", "method": "getStrategy" },
|
{ "hook": "filter:auth.init", "method": "getStrategy" }
|
||||||
{ "hook": "filter:admin.header.build", "method": "addMenuItem" }
|
|
||||||
],
|
],
|
||||||
"templates": "./templates",
|
"templates": "./templates",
|
||||||
"minver": "0.5.0"
|
"minver": "0.5.0"
|
||||||
|
Loading…
Reference in New Issue
Block a user