diff --git a/meshcentral.js b/meshcentral.js index d7aa06c2..ba79a458 100644 --- a/meshcentral.js +++ b/meshcentral.js @@ -2556,6 +2556,7 @@ function mainStart() { if ((typeof config.domains[i].authstrategies.google == 'object') && (typeof config.domains[i].authstrategies.google.clientid == 'string') && (typeof config.domains[i].authstrategies.google.clientsecret == 'string') && (passport.indexOf('passport-google-oauth20') == -1)) { passport.push('passport-google-oauth20'); } if ((typeof config.domains[i].authstrategies.github == 'object') && (typeof config.domains[i].authstrategies.github.clientid == 'string') && (typeof config.domains[i].authstrategies.github.clientsecret == 'string') && (passport.indexOf('passport-github2') == -1)) { passport.push('passport-github2'); } if ((typeof config.domains[i].authstrategies.reddit == 'object') && (typeof config.domains[i].authstrategies.reddit.clientid == 'string') && (typeof config.domains[i].authstrategies.reddit.clientsecret == 'string') && (passport.indexOf('passport-reddit') == -1)) { passport.push('passport-reddit'); } + if ((typeof config.domains[i].authstrategies.saml == 'object') || (typeof config.domains[i].authstrategies.jumpcloud == 'object')) { passport.push('passport-saml'); } } if ((config.domains[i].sessionrecording != null) && (config.domains[i].sessionrecording.index == true)) { recordingIndex = true; } } diff --git a/public/images/login/jumpcloud32.png b/public/images/login/jumpcloud32.png new file mode 100644 index 00000000..46f53e82 Binary files /dev/null and b/public/images/login/jumpcloud32.png differ diff --git a/public/images/login/jumpcloud64.png b/public/images/login/jumpcloud64.png new file mode 100644 index 00000000..cfd10e56 Binary files /dev/null and b/public/images/login/jumpcloud64.png differ diff --git a/views/default.handlebars b/views/default.handlebars index 6e52689e..09f1bb27 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -886,7 +886,7 @@ - + @@ -10884,6 +10884,7 @@ else if (shortuserid.startsWith('~google:')) { QV('p30userAuthServiceLogo', true); Q('p30userAuthServiceLogo').src = 'images/login/google64.png';; } else if (shortuserid.startsWith('~github:')) { QV('p30userAuthServiceLogo', true); Q('p30userAuthServiceLogo').src = 'images/login/github64.png';; } else if (shortuserid.startsWith('~reddit:')) { QV('p30userAuthServiceLogo', true); Q('p30userAuthServiceLogo').src = 'images/login/reddit64.png';; } + else if (shortuserid.startsWith('~jumpcloud:')) { QV('p30userAuthServiceLogo', true); Q('p30userAuthServiceLogo').src = 'images/login/jumpcloud64.png';; } else if (shortuserid.startsWith('~intel:')) { QV('p30userAuthServiceLogo', true); Q('p30userAuthServiceLogo').src = 'images/login/intel64.png';; } else { QV('p30userAuthServiceLogo', false); } diff --git a/views/login.handlebars b/views/login.handlebars index b820a35b..75e49cfa 100644 --- a/views/login.handlebars +++ b/views/login.handlebars @@ -77,6 +77,7 @@ + @@ -384,6 +385,7 @@ if (authStrategies.indexOf('google') >= 0) { QV('auth-google', true); } if (authStrategies.indexOf('github') >= 0) { QV('auth-github', true); } if (authStrategies.indexOf('reddit') >= 0) { QV('auth-reddit', true); } + if (authStrategies.indexOf('jumpcloud') >= 0) { QV('auth-jumpcloud', true); } } // Display the welcome text diff --git a/webserver.js b/webserver.js index 7d699185..191dcdf7 100644 --- a/webserver.js +++ b/webserver.js @@ -2115,6 +2115,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if ((typeof domain.authstrategies.google == 'object') && (typeof domain.authstrategies.google.clientid == 'string') && (typeof domain.authstrategies.google.clientsecret == 'string')) { authStrategies.push('google'); } if ((typeof domain.authstrategies.github == 'object') && (typeof domain.authstrategies.github.clientid == 'string') && (typeof domain.authstrategies.github.clientsecret == 'string')) { authStrategies.push('github'); } if ((typeof domain.authstrategies.reddit == 'object') && (typeof domain.authstrategies.reddit.clientid == 'string') && (typeof domain.authstrategies.reddit.clientsecret == 'string')) { authStrategies.push('reddit'); } + if ((typeof domain.authstrategies.jumpcloud == 'object')) { authStrategies.push('jumpcloud'); } if ((typeof domain.authstrategies.intel == 'object') && (typeof domain.authstrategies.intel.clientid == 'string') && (typeof domain.authstrategies.intel.clientsecret == 'string')) { authStrategies.push('intel'); } } @@ -4188,7 +4189,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { )); obj.app.get(url + 'auth-reddit', function (req, res, next) { req.session.rstate = obj.crypto.randomBytes(32).toString('hex'); - domain.passport.authenticate('reddit', { state: req.session.rstate, duration: 'permanent' })(req, res, next); // TODO: Replace 'rcookie' with a time-limited cookie + domain.passport.authenticate('reddit', { state: req.session.rstate, duration: 'permanent' })(req, res, next); }); obj.app.get(url + 'auth-reddit-callback', function (req, res, next) { if ((Object.keys(req.session).length == 0) && (req.query.nmr == null)) { @@ -4208,6 +4209,41 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { } }, handleStrategyLogin); } + + // JumpCloud + if (typeof domain.authstrategies.jumpcloud == 'object') { + const SamlStrategy = require('passport-saml').Strategy; + + var options = { + path: url + 'auth-jumpcloud-callback', + entryPoint: domain.authstrategies.jumpcloud.idpurl, + issuer: 'passport-saml' + }; + + if (domain.authstrategies.jumpcloud.cert) { + var cert = obj.fs.readFileSync(obj.path.join(obj.parent.datapath, domain.authstrategies.jumpcloud.cert)); + if (cert != null) { options.cert = cert.toString().split('-----BEGIN CERTIFICATE-----').join('').split('-----END CERTIFICATE-----').join(''); } + //console.log(options); + } + + passport.use(new SamlStrategy(options, + function (profile, done) { + //var user = { id: 'user/' + domain.id + '/~reddit:' + profile.id, name: profile.name }; + //if ((typeof profile.emails == 'object') && (profile.emails[0] != null) && (typeof profile.emails[0].value == 'string')) { user.email = profile.emails[0].value; } + console.log('JumpCloud Profile', profile); + var user = { id: 'user/' + domain.id + '/~jumpcloud:' + profile.id, name: profile.name }; + return done(null, user); + } + )); + obj.app.get(url + 'auth-jumpcloud', function (req, res, next) { + console.log('auth-jumpcloud'); + domain.passport.authenticate('saml', { failureRedirect: '/', failureFlash: true })(req, res, next); + }); + obj.app.get(url + 'auth-jumpcloud-callback', function (req, res, next) { + console.log('auth-jumpcloud-callback'); + domain.passport.authenticate('saml', { failureRedirect: '/', failureFlash: true })(req, res, next); + }); + } } // Server redirects