Doc and icons
This commit is contained in:
parent
df471d4a35
commit
50516a613b
3 changed files with 107 additions and 71 deletions
23
README.md
23
README.md
|
|
@ -1,7 +1,24 @@
|
||||||
# NodeBB Twitter SSO
|
# NodeBB SAML SSO
|
||||||
|
|
||||||
NodeBB Plugin that allows users to login/register via their Twitter account.
|
NodeBB Plugin that allows users to login/register via SAML IDP
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
npm install nodebb-plugin-sso-twitter
|
1) npm install nodebb-plugin-sso-saml
|
||||||
|
|
||||||
|
2) Activate plugin at nodebb admin panel
|
||||||
|
|
||||||
|
3) Once you activated it you can configure all the params at SAML section.
|
||||||
|
|
||||||
|
- IdP entry point: it's the saml IdP entry point. E.g https://<sever>/simplesaml/saml2/idp/SSOService.php.
|
||||||
|
- Callback path: path to callback. Eg: /auth/saml/callback.
|
||||||
|
- Issuer: issuer string to supply IdP. Eg: 'nodebb-saml'
|
||||||
|
- Metadata url: url where metadata will be served at. Optional.
|
||||||
|
- Server CRT file: Server crt path. Mandatory if used metadata url
|
||||||
|
|
||||||
|
##
|
||||||
|
If you need more info or if you need some help, please report an issue at https://github.com/GeographicaGS/nodebb-plugin-sso-saml/issues
|
||||||
|
|
||||||
|
|
||||||
|
##
|
||||||
|
This plugin has been built on top of passport.saml, for more info visit https://github.com/bergie/passport-saml
|
||||||
|
|
|
||||||
141
library.js
141
library.js
|
|
@ -15,44 +15,47 @@
|
||||||
'name': "SAML",
|
'name': "SAML",
|
||||||
'admin': {
|
'admin': {
|
||||||
'route': '/plugins/sso-saml',
|
'route': '/plugins/sso-saml',
|
||||||
'icon': 'fa-twitter-square'
|
'icon': 'fa-university'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var SAML = {};
|
var SAML = {};
|
||||||
|
var samlObj;
|
||||||
|
|
||||||
if (!meta.config['sso:saml:idpentrypoint'] || meta.config['sso:saml:callbackpath']) {
|
if (meta.config['sso:saml:idpentrypoint'] && meta.config['sso:saml:callbackpath']&& meta.config["sso:saml:metadata"] && meta.config["sso:saml:issuer"]) {
|
||||||
var err = new Error('Missing config variables');
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
samlObj = new passportSAML({
|
||||||
|
path: meta.config['sso:saml:callbackpath'],
|
||||||
|
entryPoint: meta.config['sso:saml:idpentrypoint'],
|
||||||
|
issuer: 'passport-saml',
|
||||||
|
callbackUrl: nconf.get('url') + meta.config['sso:saml:callbackpath']
|
||||||
|
},
|
||||||
|
function(profile, done) {
|
||||||
|
|
||||||
var samlObj = new passportSAML({
|
var user = {
|
||||||
path: meta.config['sso:saml:callbackpath'],
|
nameID: profile.nameID,
|
||||||
entryPoint: meta.config['sso:saml:idpentrypoint'],
|
nameIDFormat: profile.nameIDFormat,
|
||||||
issuer: 'passport-saml',
|
sn: profile.sn,
|
||||||
callbackUrl: nconf.get('url') + ':' + nconf.get('port') + meta.config['sso:saml:callbackpath']
|
cn: profile.cn,
|
||||||
},
|
mail: profile.mail,
|
||||||
function(profile, done) {
|
eduPersonAffiliation: profile.eduPersonAffiliation,
|
||||||
|
email: profile.email,
|
||||||
|
username: profile.displayName
|
||||||
|
};
|
||||||
|
|
||||||
var user = {
|
SAML.login(user.nameID,user.username,function(err, user) {
|
||||||
nameID: profile.nameID,
|
if (err) {
|
||||||
nameIDFormat: profile.nameIDFormat,
|
return done(err);
|
||||||
sn: profile.sn,
|
}
|
||||||
cn: profile.cn,
|
done(null, user);
|
||||||
mail: profile.mail,
|
});
|
||||||
eduPersonAffiliation: profile.eduPersonAffiliation,
|
}
|
||||||
email: profile.email
|
);
|
||||||
};
|
}
|
||||||
|
else{
|
||||||
SAML.login(user.nameID,user.nameID,function(err, user) {
|
console.log("No config info")
|
||||||
if (err) {
|
console.log(meta.config);
|
||||||
return done(err);
|
}
|
||||||
}
|
|
||||||
done(null, user);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
SAML.init = function(app, middleware, controllers, callback) {
|
SAML.init = function(app, middleware, controllers, callback) {
|
||||||
|
|
@ -63,36 +66,49 @@
|
||||||
app.get('/admin/plugins/sso-saml', middleware.admin.buildHeader, render);
|
app.get('/admin/plugins/sso-saml', middleware.admin.buildHeader, render);
|
||||||
app.get('/api/admin/plugins/sso-saml', render);
|
app.get('/api/admin/plugins/sso-saml', render);
|
||||||
|
|
||||||
app.get(meta.config["sso:saml:metadata"], function(req, res) {
|
if (samlObj){
|
||||||
var cert = fs.readFileSync('/Users/alasarr/dev/nodebb/node_modules/nodebb-plugin-sso-saml/server.crt', 'utf-8');
|
|
||||||
res.header("Content-Type", "application/xml");
|
|
||||||
res.send(samlObj.generateServiceProviderMetadata(cert))
|
|
||||||
|
|
||||||
});
|
if (meta.config["sso:saml:metadata"]) {
|
||||||
|
app.get(meta.config["sso:saml:metadata"], function(req, res) {
|
||||||
|
if (meta.config["sso:saml:servercrt"]){
|
||||||
|
var cert = fs.readFileSync(meta.config["sso:saml:servercrt"], 'utf-8');
|
||||||
|
res.header("Content-Type", "application/xml");
|
||||||
|
res.send(samlObj.generateServiceProviderMetadata(cert))
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
res.send("No servercrt specified. Please enter it at nodebb admin panel.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
app.post(meta.config['sso:saml:callbackpath'],
|
|
||||||
passport.authenticate('saml', { successRedirect: '/',failureRedirect: '/', failureFlash: true })
|
app.post(meta.config['sso:saml:callbackpath'],
|
||||||
);
|
passport.authenticate('saml', { successRedirect: '/',failureRedirect: '/', failureFlash: true })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
};
|
};
|
||||||
|
|
||||||
SAML.getStrategy = function(strategies, callback) {
|
SAML.getStrategy = function(strategies, callback) {
|
||||||
|
|
||||||
passport.use(samlObj);
|
if (samlObj){
|
||||||
|
|
||||||
strategies.push({
|
passport.use(samlObj);
|
||||||
name: 'saml',
|
|
||||||
url: '/auth/saml',
|
strategies.push({
|
||||||
callbackURL: meta.config['sso:saml:callbackpath'],
|
name: 'saml',
|
||||||
icon: constants.admin.icon,
|
url: '/auth/saml',
|
||||||
scope: ''
|
callbackURL: meta.config['sso:saml:callbackpath'],
|
||||||
});
|
icon: constants.admin.icon,
|
||||||
|
scope: ''
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
callback(null, strategies);
|
callback(null, strategies);
|
||||||
};
|
};
|
||||||
|
|
||||||
SAML.login = function(samlid,email, callback) {
|
SAML.login = function(samlid,username, callback) {
|
||||||
|
|
||||||
SAML.getUidBySAMLId(samlid, function(err, uid) {
|
SAML.getUidBySAMLId(samlid, function(err, uid) {
|
||||||
if(err) {
|
if(err) {
|
||||||
|
|
@ -102,11 +118,12 @@
|
||||||
if (uid !== null) {
|
if (uid !== null) {
|
||||||
// Existing User
|
// Existing User
|
||||||
callback(null, {
|
callback(null, {
|
||||||
uid: uid
|
uid: uid
|
||||||
});
|
});
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// New User
|
// New User
|
||||||
user.create({username: email}, function(err, uid) {
|
user.create({username: username}, function(err, uid) {
|
||||||
if(err) {
|
if(err) {
|
||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
|
|
@ -142,18 +159,18 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
SAML.deleteUserData = function(uid, callback) {
|
SAML.deleteUserData = function(uid, callback) {
|
||||||
// async.waterfall([
|
async.waterfall([
|
||||||
// async.apply(user.getUserField, uid, 'samlid'),
|
async.apply(user.getUserField, uid, 'samlid'),
|
||||||
// function(oAuthIdToDelete, next) {
|
function(idToDelete, next) {
|
||||||
// db.deleteObjectField('twid:uid', oAuthIdToDelete, next);
|
db.deleteObjectField('samlid:uid', idToDelete, next);
|
||||||
// }
|
}
|
||||||
// ], function(err) {
|
], function(err) {
|
||||||
// if (err) {
|
if (err) {
|
||||||
// winston.error('[sso-twitter] Could not remove OAuthId data for uid ' + uid + '. Error: ' + err);
|
winston.error('[sso-saml] Could not remove user data for uid ' + uid + '. Error: ' + err);
|
||||||
// return callback(err);
|
return callback(err);
|
||||||
// }
|
}
|
||||||
// callback(null, uid);
|
callback(null, uid);
|
||||||
// });
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = SAML;
|
module.exports = SAML;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<h1><i class="fa fa-twitter-square"></i> Simple samp Authentication</h1>
|
<h1> Simple samp Authentication</h1>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<form>
|
<form>
|
||||||
|
|
@ -10,7 +10,9 @@
|
||||||
<input type="text" data-field="sso:saml:idpentrypoint" title="IdP entry point" class="form-control input-lg" placeholder="IdP entry point"><br />
|
<input type="text" data-field="sso:saml:idpentrypoint" title="IdP entry point" class="form-control input-lg" placeholder="IdP entry point"><br />
|
||||||
<input type="text" data-field="sso:saml:callbackpath" title="Callback path" class="form-control input-md" placeholder="Callback path"><br/>
|
<input type="text" data-field="sso:saml:callbackpath" title="Callback path" class="form-control input-md" placeholder="Callback path"><br/>
|
||||||
<input type="text" data-field="sso:saml:issuer" title="Issuer string to supply to identity provider" class="form-control input-md" placeholder="Issuer string to supply to identity provider"><br/>
|
<input type="text" data-field="sso:saml:issuer" title="Issuer string to supply to identity provider" class="form-control input-md" placeholder="Issuer string to supply to identity provider"><br/>
|
||||||
<input type="text" data-field="sso:saml:metadata" title="Metadata URL" class="form-control input-md" placeholder="Metadata URL">
|
<input type="text" data-field="sso:saml:metadata" title="Metadata URL" class="form-control input-md" placeholder="Metadata URL"><br/>
|
||||||
|
|
||||||
|
<input type="text" data-field="sso:saml:servercrt" title="Server CRT file" class="form-control input-md" placeholder="Server CRT file">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue