From 7b1c553ca83bcf58178cfe8a24aa4e8b72e00e52 Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Tue, 19 May 2020 19:02:27 -0700 Subject: [PATCH] Started work on added JumpCloud support. --- meshcentral.js | 1 + public/images/login/jumpcloud32.png | Bin 0 -> 956 bytes public/images/login/jumpcloud64.png | Bin 0 -> 2389 bytes views/default.handlebars | 3 ++- views/login.handlebars | 2 ++ webserver.js | 38 +++++++++++++++++++++++++++- 6 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 public/images/login/jumpcloud32.png create mode 100644 public/images/login/jumpcloud64.png 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 0000000000000000000000000000000000000000..46f53e82670541c1b7ffa07648b142ba482bba5e GIT binary patch literal 956 zcmV;t14I0YP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D15rstK~zXfWBmXB zKLafR6O^VI7`1>P7`1>PAR!;T`}Y0jtG8UNtQz7X>@3VsQ9^(y3vRuB*R=D<(fd#S zffaMJvW6OHlsZ}Pu(LrF-~og!IQj5t!t$-(e*K2>VL)9>Xi1Ep00##fUf&R~;N$n7 z4%3#t`}!TqM+Hob42+D7nqnd;mIeX3YK%}}6oAtLpy<`-uNR-Wvf}(Ts1OYBbF$~! z7`v(~ak8<#|N4E+#q0A=U5YW$Y4oszsz3tREx7#rRoSNfci+7Sx(*obH(tK|_4hAC zN|c*xX{_I-tGAb)x%%Pz4;ca8A_p^m4vzHI+ouM*yK5*xl)(YQ0wCkw+Yj%){rL6w zPuj}u-dZXJ_NF&py#q?AiwbrhIJN%LO(1(lsK+f{)<=dOD-!F>xg$ls{ z)PjpoUzTjzd+YUkh-jd$T8yzy+Ugx|zkUOTtT-?C%rMXCN6(#l^lU?Ni2anMX#SSu zlFWm4Xy2GZQfMfKkH42#OR?Mtk`FW7LvOaMPI?84B&qa@XwwnhxXwO?vV9 zYySG(#SUh2g8a8$y~7OE=byjvao}C&0_f%p7m3iyRVRh8nq zfQ^}XW*9I9KU{eF3Xm%=$iF!?l%IngnoQq*{oc0c=&l?0Ck4Chzx81CrJHE+s3$4f z=xG-;e=SA|LI6Qd4xphvvq6cq+}T2uhZ`t}l9Pc6i-`$Xz)%yQSU?K^ie#FCQ40uy eQ40tF1_l5RaBp^TpCW7k000000001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D2%qbv#Ziw^J$VKd3cv&t+BsCgnff4@%fs8=V(Io5WJGZU zS8?1(*6n6IM8=o*V9*a`tlS>Ah=NUspJ(yB0`mC9cRRZAi6LtR6hSEzEHgYLYhhSy zpg+@v4huh#4^?;d6*adCC32z%j=vfkah#V)#q7PH{ucoTqp_+>BnJ+D0=8lrv^e4fFJnZb-GBK;d3z762`LN&J^T<|QN)!_eJ3kU~w_f2~!=*PTv-{=*z~|H;TT3ZWnTM(!xW?9@eoeK&Lmf z^hw}om#I|l4Eh2Nn_t^-OV|S|ZCMg|EN3lj-zHK2*KOSo`v<|vG5(zFnD8(T8#eK; zuap(HJcfB;9{4-Cam|*c(Z9WR=R!@hd2(wosMyWj+e6r__2(`&>MqfYWNKB;VY=lVB`gM8jt zo%l#1bD>e9{e9!O{uYy{Ndn+b-St^%MVAOB8&Ac?31WHP+P4F?N-n>+p-+lVJNrTK z@{oYSojjN)^=yGcHtOJ&KyD@4H{8%_3U3dO6j_6I{gn}0h zsFCC9wlg7iU-B{++9VlIk6W!?|HF$VmEFBy`84Z^`o2|hF!;T%?>F@IBbIJ1cvY3% z;xmG3j=S6LqjIerXCv@9rg8eM^FPs*hZKETa04Hp*2)uml7hn5H*Z_{RYHgpQ+Mx*J*^eAfKCPooBqmd@@;Ggf-kxko&LWoj+tGZ1`TvJq%l#`Q-m88iiOdIX2<<>uNb>cg!& z2`-RNs~bnPI&+nr_iiWTGd4VnYmLMi;%7&;2rrRp%Ek=1Q8*xPlMJp53y$*jGC#Ee zoMv0&qM>k8*ojTrK~umLWBPmTPs|lkfK;h57c64L(6+uo$Ri^CU^Cd5ngFhd*Z@B` zhz3;}BVzdIemw=l-pX2K+7-6OE(+l6SQaB4RbG40F*yXL0x? zTKL|Lo#(g6-v<&(poEty2$*QKY1y4YG{X1tEvlB-)6CP;chh%`Y*i zl*6UvD&5lWc&CNtG(4Ru|8mcbd1>a<~|=Q=8JbY}Sxk4JRqAQMBu|y~zoXM;*L!EBOpxI50@| zoW{|znwQW0?Mh2)h&P+RgLiPva+?Zp_#8Et$eS2^w*Gvfuz$#sWyGy~AUR=gY9bV> zyF?!ds_u35PLFvU#WTWR*taS^AtX>UriVKlPTos(&40L2F{0DjG>8B?7;$7(829~G z(z#yD{L1>bZ+v6&>7=1hSv=3TWEYVj64mi5=6**{-o+BVaoYYyk;7Rlf3za5cWC%m zSMJ<>+-+*KZV!s=TCw;ySt(Hbu)O-%oeIo=S$<#N!hb9-dr^^HJt`zN>yQ9%k_UhZj%jtz+1a6I{eeBhBM{0?THNOaKObh3JKR(ub+D&Rfz&MaIL1qGOAnV^rYzdeX ze5bu@4^9D&#wozjI0ZNwrvOLe6yRu_0vwG~fTNk?0ubasBe=_Ms6#Gl00000NkvXX Hu0mjf2xE1< literal 0 HcmV?d00001 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