More OAuth work.

Ylian Saint-Hilaire committed May 14, 2020 at 01:41 UTC 7ca1e1e9070ec027b96225a0a624e55670eddb7e
10 files changed +166 -58
meshcentral.js
+1
@@ -2555,6 +2555,7 @@ function mainStart() {
2555 if ((typeof config.domains[i].authstrategies.twitter == 'object') && (typeof config.domains[i].authstrategies.twitter.apikey == 'string') && (typeof config.domains[i].authstrategies.twitter.apisecret == 'string') && (passport.indexOf('passport-twitter') == -1)) { passport.push('passport-twitter'); }
2556 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'); }
2557 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'); }
2558 + 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'); }
2559 }
2560 if ((config.domains[i].sessionrecording != null) && (config.domains[i].sessionrecording.index == true)) { recordingIndex = true; }
2561 }
public/images/login/intel32.png
Binary files /dev/null and b/public/images/login/intel32.png differ
public/images/login/intel64.png
Binary files /dev/null and b/public/images/login/intel64.png differ
public/images/login/reddit32.png
Binary files /dev/null and b/public/images/login/reddit32.png differ
public/images/login/reddit64.png
Binary files /dev/null and b/public/images/login/reddit64.png differ
translate/translate.json
+56 -15
@@ -1891,7 +1891,7 @@
1891 "ru": "Действия учетной записи",
1892 "zh-chs": "帳戶動作",
1893 "xloc": [
1894 - "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->5->0"
1894 + "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->3->0"
1895 ]
1896 },
1897 {
@@ -1948,7 +1948,7 @@
1948 "default-mobile.handlebars->9->154",
1949 "default-mobile.handlebars->9->62",
1950 "default-mobile.handlebars->9->64",
1951 - "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->1->0",
1951 + "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->p2AccountSecurity->1->0",
1952 "default.handlebars->25->1115",
1953 "default.handlebars->25->1117",
1954 "default.handlebars->25->461",
@@ -5066,7 +5066,7 @@
5066 "ru": "Смена email",
5067 "zh-chs": "更改電子郵件地址",
5068 "xloc": [
5069 - "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->7->5->changeEmailId->0",
5069 + "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->5->5->changeEmailId->0",
5070 "default.handlebars->container->column_l->p2->p2info->p2AccountActions->3->p2AccountPassActions->accountChangeEmailAddressSpan->0"
5071 ]
5072 },
@@ -5084,7 +5084,7 @@
5084 "ru": "Смена пароля",
5085 "zh-chs": "更改密碼",
5086 "xloc": [
5087 - "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->7->7->0",
5087 + "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->5->7->0",
5088 "default.handlebars->container->column_l->p2->p2info->p2AccountActions->3->p2AccountPassActions->3"
5089 ]
5090 },
@@ -7630,7 +7630,7 @@
7630 "ru": "Удалить учетную запись",
7631 "zh-chs": "刪除帳戶",
7632 "xloc": [
7633 - "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->7->9->0",
7633 + "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->5->9->0",
7634 "default.handlebars->25->1442",
7635 "default.handlebars->container->column_l->p2->p2info->p2AccountActions->3->p2AccountPassActions->7"
7636 ]
@@ -15495,6 +15495,13 @@
15495 "login.handlebars->container->column_l->centralTable->1->0->logincell->loginpanel->1->7->1->4->3"
15496 ]
15497 },
15498 + {
15499 + "en": "Log in using an existing account",
15500 + "xloc": [
15501 + "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->loginpanel->1->authStrategies->3",
15502 + "login.handlebars->container->column_l->centralTable->1->0->logincell->loginpanel->1->authStrategies->3"
15503 + ]
15504 + },
15505 {
15506 "cs": "Log-X",
15507 "de": "Logarithmische Skala",
@@ -16157,7 +16164,7 @@
16164 "ru": "Управление приложением для проверки подлинности",
16165 "zh-chs": "管理身份驗證器應用",
16166 "xloc": [
16160 - "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->3->manageAuthApp->0",
16167 + "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->p2AccountSecurity->3->manageAuthApp->0",
16168 "default.handlebars->container->column_l->p2->p2info->p2AccountSecurity->3->manageAuthApp->1->0"
16169 ]
16170 },
@@ -16175,7 +16182,7 @@
16182 "ru": "Управление резервными кодами",
16183 "zh-chs": "管理備用碼",
16184 "xloc": [
16178 - "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->3->manageOtp->0",
16185 + "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->p2AccountSecurity->3->manageOtp->0",
16186 "default.handlebars->container->column_l->p2->p2info->p2AccountSecurity->3->manageOtp->1->0"
16187 ]
16188 },
@@ -16193,7 +16200,7 @@
16200 "ru": "Управление аутентификацией электронной почты",
16201 "zh-chs": "管理電子郵件身份驗證",
16202 "xloc": [
16196 - "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->3->manageEmail2FA->0",
16203 + "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->p2AccountSecurity->3->manageEmail2FA->0",
16204 "default.handlebars->container->column_l->p2->p2info->p2AccountSecurity->3->manageEmail2FA->1->0"
16205 ]
16206 },
@@ -16207,8 +16214,8 @@
16214 "nl": "Beheer telefoonnummer",
16215 "zh-chs": "管理电话号码",
16216 "xloc": [
16210 - "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->3->managePhoneNumber1->0",
16211 - "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->7->1->managePhoneNumber2->0",
16217 + "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->5->1->managePhoneNumber2->0",
16218 + "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->p2AccountSecurity->3->managePhoneNumber1->0",
16219 "default.handlebars->container->column_l->p2->p2info->p2AccountActions->3->managePhoneNumber2->0",
16220 "default.handlebars->container->column_l->p2->p2info->p2AccountSecurity->3->managePhoneNumber1->1->0"
16221 ]
@@ -23900,6 +23907,40 @@
23907 "default.handlebars->container->column_l->p6->p6info->p2ServerActions->3->p2ServerActionsErrors->0"
23908 ]
23909 },
23910 + {
23911 + "en": "Sign-in using GitHub",
23912 + "xloc": [
23913 + "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->loginpanel->1->authStrategies->auth-github",
23914 + "login.handlebars->container->column_l->centralTable->1->0->logincell->loginpanel->1->authStrategies->auth-github"
23915 + ]
23916 + },
23917 + {
23918 + "en": "Sign-in using Google",
23919 + "xloc": [
23920 + "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->loginpanel->1->authStrategies->auth-google",
23921 + "login.handlebars->container->column_l->centralTable->1->0->logincell->loginpanel->1->authStrategies->auth-google"
23922 + ]
23923 + },
23924 + {
23925 + "en": "Sign-in using Intel",
23926 + "xloc": [
23927 + "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->loginpanel->1->authStrategies->auth-intel"
23928 + ]
23929 + },
23930 + {
23931 + "en": "Sign-in using Reddit",
23932 + "xloc": [
23933 + "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->loginpanel->1->authStrategies->auth-reddit",
23934 + "login.handlebars->container->column_l->centralTable->1->0->logincell->loginpanel->1->authStrategies->auth-reddit"
23935 + ]
23936 + },
23937 + {
23938 + "en": "Sign-in using Twitter",
23939 + "xloc": [
23940 + "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->loginpanel->1->authStrategies->auth-twitter",
23941 + "login.handlebars->container->column_l->centralTable->1->0->logincell->loginpanel->1->authStrategies->auth-twitter"
23942 + ]
23943 + },
23944 {
23945 "cs": "Jednoduchý režim řízený správcem (ACM)",
23946 "de": "Einfacher Admin Control Mode (ACM)",
@@ -27958,7 +27999,7 @@
27999 "ru": "Подтвердить email",
28000 "zh-chs": "驗證郵件",
28001 "xloc": [
27961 - "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->7->3->verifyEmailId->0",
28002 + "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->5->3->verifyEmailId->0",
28003 "default.handlebars->container->column_l->p2->p2info->p2AccountActions->3->verifyEmailId->0"
28004 ]
28005 },
@@ -30992,10 +31033,10 @@
31033 "ru": "✓",
31034 "ko": "✓",
31035 "xloc": [
30995 - "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->3->manageAuthApp->authAppSetupCheck->0",
30996 - "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->3->manageEmail2FA->authEmailSetupCheck->0",
30997 - "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->3->manageOtp->authCodesSetupCheck->0",
30998 - "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->3->managePhoneNumber1->authPhoneNumberCheck->0",
31036 + "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->p2AccountSecurity->3->manageAuthApp->authAppSetupCheck->0",
31037 + "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->p2AccountSecurity->3->manageEmail2FA->authEmailSetupCheck->0",
31038 + "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->p2AccountSecurity->3->manageOtp->authCodesSetupCheck->0",
31039 + "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->p2AccountSecurity->3->managePhoneNumber1->authPhoneNumberCheck->0",
31040 "default.handlebars->container->column_l->p13->p13filetable->p13bigok->0",
31041 "default.handlebars->container->column_l->p2->p2info->p2AccountSecurity->3->manageAuthApp->0->authAppSetupCheck->0",
31042 "default.handlebars->container->column_l->p2->p2info->p2AccountSecurity->3->manageEmail2FA->0->authEmailSetupCheck->0",
views/default-mobile.handlebars
+8 -5
@@ -295,12 +295,14 @@
295 <div id=p3info style="overflow-y:scroll;position:absolute;top:55px;bottom:0px;width:100%">
296 <div style="margin-left:8px">
297 <div id="p3AccountActions">
298 + <div id="p2AccountSecurity" style="display:none">
299 <p><strong>Account Security</strong></p>
299 - <div style="margin-left:9px;margin-bottom:8px">
300 - <div id="managePhoneNumber1" style="margin-top:5px;display:none"><a onclick="account_managePhone()" style="cursor:pointer">Manage phone number</a> <span id="authPhoneNumberCheck"><strong>&#x2713;</strong></span></div>
301 - <div id="manageEmail2FA" style="margin-top:5px;display:none"><a onclick="account_manageAuthEmail()" style="cursor:pointer">Manage email authentication</a> <span id="authEmailSetupCheck"><strong>&#x2713;</strong></span></div>
302 - <div id="manageAuthApp" style="margin-top:5px;display:none"><a onclick="account_manageAuthApp()" style="cursor:pointer">Manage authenticator app</a> <span id="authAppSetupCheck"><strong>&#x2713;</strong></span></div>
303 - <div id="manageOtp" style="margin-top:5px;display:none"><a onclick="account_manageOtp(0)" style="cursor:pointer">Manage backup codes</a> <span id="authCodesSetupCheck"><strong>&#x2713;</strong></span></div>
300 + <div style="margin-left:9px;margin-bottom:8px">
301 + <div id="managePhoneNumber1" style="margin-top:5px;display:none"><a onclick="account_managePhone()" style="cursor:pointer">Manage phone number</a> <span id="authPhoneNumberCheck"><strong>&#x2713;</strong></span></div>
302 + <div id="manageEmail2FA" style="margin-top:5px;display:none"><a onclick="account_manageAuthEmail()" style="cursor:pointer">Manage email authentication</a> <span id="authEmailSetupCheck"><strong>&#x2713;</strong></span></div>
303 + <div id="manageAuthApp" style="margin-top:5px;display:none"><a onclick="account_manageAuthApp()" style="cursor:pointer">Manage authenticator app</a> <span id="authAppSetupCheck"><strong>&#x2713;</strong></span></div>
304 + <div id="manageOtp" style="margin-top:5px;display:none"><a onclick="account_manageOtp(0)" style="cursor:pointer">Manage backup codes</a> <span id="authCodesSetupCheck"><strong>&#x2713;</strong></span></div>
305 + </div>
306 </div>
307 <p><strong>Account Actions</strong></p>
308 <div style="margin-left:9px;margin-bottom:8px">
@@ -791,6 +793,7 @@
793 if (serverinfo.timeout) { setInterval(checkIdleSessionTimeout, 10000); checkIdleSessionTimeout(); }
794 QV('p3AccountActions', ((features & 4) == 0) && (serverinfo.domainauth == false)); // Hide Account Actions if in single user mode or domain authentication
795 QV('logoutMenuOption', ((features & 4) == 0) && (serverinfo.domainauth == false)); // Hide logout if in single user mode or domain authentication
796 + QV('p2AccountSecurity', ((features & 4) == 0) && (serverinfo.domainauth == false) && ((features & 4096) != 0)); // Hide Account Security if in single user mode or domain authentication, 2 factor auth not supported.
797 break;
798 }
799 case 'authcookie': {
views/login-mobile.handlebars
+20
@@ -72,6 +72,15 @@
72 Don&#39;t have an account? <a onclick=xgo(2) style=cursor:pointer>Create one</a>.
73 </div>
74 <input id=loginformargs name="urlargs" type="hidden" value="" />
75 + <div id="authStrategies" style="display:none">
76 + <hr />
77 + <div style="margin-bottom:8px">Log in using an existing account</div>
78 + <a id="auth-twitter" href="auth-twitter" style="display:none"><img src="images/login/twitter32.png" loading="lazy" width="32" height="32" style="margin-left:3px;margin-right:3px;border-radius:3px;box-shadow:2px 2px 5px black;cursor:pointer" title="Sign-in using Twitter" /></a>
79 + <a id="auth-google" href="auth-google" style="display:none"><img src="images/login/google32.png" loading="lazy" width="32" height="32" style="margin-left:3px;margin-right:3px;border-radius:3px;box-shadow:2px 2px 5px black;cursor:pointer" title="Sign-in using Google" /></a>
80 + <a id="auth-github" href="auth-github" style="display:none"><img src="images/login/github32.png" loading="lazy" width="32" height="32" style="margin-left:3px;margin-right:3px;border-radius:3px;box-shadow:2px 2px 5px black;cursor:pointer" title="Sign-in using GitHub" /></a>
81 + <a id="auth-reddit" href="auth-reddit" style="display:none"><img src="images/login/reddit32.png" loading="lazy" width="32" height="32" style="margin-left:3px;margin-right:3px;border-radius:3px;box-shadow:2px 2px 5px black;cursor:pointer" title="Sign-in using Reddit" /></a>
82 + <a id="auth-intel" href="auth-intel" style="display:none"><img src="images/login/intel32.png" loading="lazy" width="32" height="32" style="margin-left:3px;margin-right:3px;border-radius:3px;box-shadow:2px 2px 5px black;cursor:pointer" title="Sign-in using Intel" /></a>
83 + </div>
84 </form>
85 </div>
86 <div id=createpanel style="display:none">
@@ -303,6 +312,7 @@
312 var otpemail = ('{{{otpemail}}}' === 'true');
313 var otpsms = ('{{{otpsms}}}' === 'true');
314 var twoFactorCookieDays = parseInt('{{{twoFactorCookieDays}}}');
315 + var authStrategies = '{{{authStrategies}}}'.split(',');
316
317 // Display the right server message
318 var messageid = parseInt('{{{messageid}}}');
@@ -354,6 +364,16 @@
364 QV('createPanelHint', passRequirements.hint === true);
365 QV('resetpasswordpanelHint', passRequirements.hint === true);
366
367 + // Setup authentication strategies
368 + if (authStrategies != '') {
369 + QV('authStrategies', true);
370 + if (authStrategies.indexOf('twitter') >= 0) { QV('auth-twitter', true); }
371 + if (authStrategies.indexOf('google') >= 0) { QV('auth-google', true); }
372 + if (authStrategies.indexOf('github') >= 0) { QV('auth-github', true); }
373 + if (authStrategies.indexOf('reddit') >= 0) { QV('auth-reddit', true); }
374 + if (authStrategies.indexOf('intel') >= 0) { QV('auth-intel', true); }
375 + }
376 +
377 window.onresize = center;
378 center();
379 validateLogin();
views/login.handlebars
+2
@@ -76,6 +76,7 @@
76 <a id="auth-twitter" href="auth-twitter" style="display:none"><img src="images/login/twitter32.png" loading="lazy" width="32" height="32" style="margin-left:3px;margin-right:3px;border-radius:3px;box-shadow:2px 2px 5px black;cursor:pointer" title="Sign-in using Twitter" /></a>
77 <a id="auth-google" href="auth-google" style="display:none"><img src="images/login/google32.png" loading="lazy" width="32" height="32" style="margin-left:3px;margin-right:3px;border-radius:3px;box-shadow:2px 2px 5px black;cursor:pointer" title="Sign-in using Google" /></a>
78 <a id="auth-github" href="auth-github" style="display:none"><img src="images/login/github32.png" loading="lazy" width="32" height="32" style="margin-left:3px;margin-right:3px;border-radius:3px;box-shadow:2px 2px 5px black;cursor:pointer" title="Sign-in using GitHub" /></a>
79 + <a id="auth-reddit" href="auth-reddit" style="display:none"><img src="images/login/reddit32.png" loading="lazy" width="32" height="32" style="margin-left:3px;margin-right:3px;border-radius:3px;box-shadow:2px 2px 5px black;cursor:pointer" title="Sign-in using Reddit" /></a>
80 </div>
81 </form>
82 </div>
@@ -382,6 +383,7 @@
383 if (authStrategies.indexOf('twitter') >= 0) { QV('auth-twitter', true); }
384 if (authStrategies.indexOf('google') >= 0) { QV('auth-google', true); }
385 if (authStrategies.indexOf('github') >= 0) { QV('auth-github', true); }
386 + if (authStrategies.indexOf('reddit') >= 0) { QV('auth-reddit', true); }
387 }
388
389 // Display the welcome text
webserver.js
+79 -38
@@ -1678,6 +1678,44 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1678 });
1679 }
1680
1681 + // Called when a strategy login occured
1682 + // This is called after a succesful Oauth to Twitter, Google, GitHub...
1683 + function handleStrategyLogin(req, res) {
1684 + const domain = checkUserIpAddress(req, res);
1685 + if (domain == null) { return; }
1686 + parent.debug('web', 'handleStrategyLogin: ' + JSON.stringify(req.user));
1687 + if ((req.user != null) && (req.user.id != null) && (domain.id == req.user.id.split('/')[1])) {
1688 + const userid = req.user.id;
1689 + var user = obj.users[userid];
1690 + if (user == null) {
1691 + // Create the user
1692 + parent.debug('web', 'handleStrategyLogin: creating new user: ' + userid);
1693 + user = { type: 'user', _id: userid, name: req.user.name, email: req.user.email, domain: domain.id };
1694 + if (req.user.email != null) { user.email = req.user.email; user.emailVerified = true; }
1695 + obj.users[userid] = user;
1696 + obj.db.SetUser(user);
1697 + // TODO: Event user creation
1698 + req.session.userid = req.user.id;
1699 + req.session.domainid = domain.id;
1700 + } else {
1701 + // Login success
1702 + var userChange = false;
1703 + if ((req.user.name != null) && (req.user.name != user.name)) { user.name = req.user.name; userChange = true; }
1704 + if ((req.user.email != null) && (req.user.email != user.email)) { user.email = req.user.email; user.emailVerified = true; userChange = true; }
1705 + if (userChange) {
1706 + obj.db.SetUser(user);
1707 + // TODO: Event user change
1708 + }
1709 + parent.debug('web', 'handleStrategyLogin: succesful login: ' + userid);
1710 + req.session.userid = req.user.id;
1711 + req.session.domainid = domain.id;
1712 + }
1713 + }
1714 + //res.redirect(domain.url); // This does not handle cookie correctly.
1715 + res.set('Content-Type', 'text/html');
1716 + res.end('<html><head><meta http-equiv="refresh" content=0;url="' + domain.url + '"></head><body></body></html>');
1717 + }
1718 +
1719 // Indicates that any request to "/" should render "default" or "login" depending on login state
1720 function handleRootRequest(req, res, direct) {
1721 const domain = checkUserIpAddress(req, res);
@@ -1865,7 +1903,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1903 if (obj.args.allowhighqualitydesktop !== false) { features += 0x00000200; } // Enable AllowHighQualityDesktop (Default true)
1904 if (obj.args.lanonly == true || obj.args.mpsport == 0) { features += 0x00000400; } // No CIRA
1905 if ((obj.parent.serverSelfWriteAllowed == true) && (user != null) && (user.siteadmin == 0xFFFFFFFF)) { features += 0x00000800; } // Server can self-write (Allows self-update)
1868 - if ((parent.config.settings.no2factorauth !== true) && (domain.auth != 'sspi') && (obj.parent.certificates.CommonName.indexOf('.') != -1) && (obj.args.nousers !== true)) { features += 0x00001000; } // 2-step login supported
1906 + if ((parent.config.settings.no2factorauth !== true) && (domain.auth != 'sspi') && (obj.parent.certificates.CommonName.indexOf('.') != -1) && (obj.args.nousers !== true) && (user._id.split('/')[2][0] != '~')) { features += 0x00001000; } // 2FA login supported
1907 if (domain.agentnoproxy === true) { features += 0x00002000; } // Indicates that agents should be installed without using a HTTP proxy
1908 if ((parent.config.settings.no2factorauth !== true) && domain.yubikey && domain.yubikey.id && domain.yubikey.secret) { features += 0x00004000; } // Indicates Yubikey support
1909 if (domain.geolocation == true) { features += 0x00008000; } // Enable geo-location features
@@ -1997,6 +2035,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
2035 if ((typeof domain.authstrategies.twitter == 'object') && (typeof domain.authstrategies.twitter.apikey == 'string') && (typeof domain.authstrategies.twitter.apisecret == 'string')) { authStrategies.push('twitter'); }
2036 if ((typeof domain.authstrategies.google == 'object') && (typeof domain.authstrategies.google.clientid == 'string') && (typeof domain.authstrategies.google.clientsecret == 'string')) { authStrategies.push('google'); }
2037 if ((typeof domain.authstrategies.github == 'object') && (typeof domain.authstrategies.github.clientid == 'string') && (typeof domain.authstrategies.github.clientsecret == 'string')) { authStrategies.push('github'); }
2038 + if ((typeof domain.authstrategies.reddit == 'object') && (typeof domain.authstrategies.reddit.clientid == 'string') && (typeof domain.authstrategies.reddit.clientsecret == 'string')) { authStrategies.push('reddit'); }
2039 + if ((typeof domain.authstrategies.intel == 'object') && (typeof domain.authstrategies.intel.clientid == 'string') && (typeof domain.authstrategies.intel.clientsecret == 'string')) { authStrategies.push('intel'); }
2040 }
2041
2042 // Render the login page
@@ -3997,19 +4037,17 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
4037 obj.app.get(url + 'pluginHandler.js', obj.handlePluginJS);
4038 }
4039
4000 - // Setup passport if needed
4040 + // Setup auth strategies using passport if needed
4041 if (typeof domain.authstrategies == 'object') {
4042 const passport = domain.passport = require('passport');
4043 passport.serializeUser(function (user, done) { done(null, user.id); });
4044 passport.deserializeUser(function (id, done) { done(null, { id: id }); });
4045 obj.app.use(passport.initialize());
4046 +
4047 + // Twitter
4048 if ((typeof domain.authstrategies.twitter == 'object') && (typeof domain.authstrategies.twitter.apikey == 'string') && (typeof domain.authstrategies.twitter.apisecret == 'string')) {
4049 const TwitterStrategy = require('passport-twitter');
4008 - passport.use(new TwitterStrategy({
4009 - consumerKey: domain.authstrategies.twitter.apikey,
4010 - consumerSecret: domain.authstrategies.twitter.apisecret,
4011 - callbackURL: url + 'auth-twitter-callback'
4012 - },
4050 + passport.use(new TwitterStrategy({ consumerKey: domain.authstrategies.twitter.apikey, consumerSecret: domain.authstrategies.twitter.apisecret, callbackURL: url + 'auth-twitter-callback' },
4051 function (token, tokenSecret, profile, cb) {
4052 var user = { id: 'user/' + domain.id + '/~twitter:' + profile.id, name: profile.displayName };
4053 if ((typeof profile.emails == 'object') && (profile.emails[0] != null) && (typeof profile.emails[0].value == 'string')) { user.email = profile.emails[0].value; }
@@ -4017,21 +4055,13 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
4055 }
4056 ));
4057 obj.app.get(url + 'auth-twitter', domain.passport.authenticate('twitter'));
4020 - obj.app.get(url + 'auth-twitter-callback',
4021 - domain.passport.authenticate('twitter', { failureRedirect: '/' }),
4022 - function (req, res) {
4023 - // Successful authentication, redirect home.
4024 - console.log('Twitter', req.session, req.user);
4025 - res.redirect('/');
4026 - });
4058 + obj.app.get(url + 'auth-twitter-callback', domain.passport.authenticate('twitter', { failureRedirect: '/' }), handleStrategyLogin);
4059 }
4060 +
4061 + // Google
4062 if ((typeof domain.authstrategies.google == 'object') && (typeof domain.authstrategies.google.clientid == 'string') && (typeof domain.authstrategies.google.clientsecret == 'string')) {
4063 const GoogleStrategy = require('passport-google-oauth20');
4030 - passport.use(new GoogleStrategy({
4031 - clientID: domain.authstrategies.google.clientid,
4032 - clientSecret: domain.authstrategies.google.clientsecret,
4033 - callbackURL: url + 'auth-google-callback'
4034 - },
4064 + passport.use(new GoogleStrategy({ clientID: domain.authstrategies.google.clientid, clientSecret: domain.authstrategies.google.clientsecret, callbackURL: url + 'auth-google-callback' },
4065 function (token, tokenSecret, profile, cb) {
4066 var user = { id: 'user/' + domain.id + '/~google:' + profile.id, name: profile.displayName };
4067 if ((typeof profile.emails == 'object') && (profile.emails[0] != null) && (typeof profile.emails[0].value == 'string') && (profile.emails[0].verified == true)) { user.email = profile.emails[0].value; }
@@ -4039,21 +4069,13 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
4069 }
4070 ));
4071 obj.app.get(url + 'auth-google', domain.passport.authenticate('google', { scope: ['profile', 'email'] }));
4042 - obj.app.get(url + 'auth-google-callback',
4043 - domain.passport.authenticate('google', { failureRedirect: '/' }),
4044 - function (req, res) {
4045 - // Successful authentication, redirect home.
4046 - console.log('Google', req.session, req.user);
4047 - res.redirect('/');
4048 - });
4072 + obj.app.get(url + 'auth-google-callback', domain.passport.authenticate('google', { failureRedirect: '/' }), handleStrategyLogin);
4073 }
4074 +
4075 + // Github
4076 if ((typeof domain.authstrategies.github == 'object') && (typeof domain.authstrategies.github.clientid == 'string') && (typeof domain.authstrategies.github.clientsecret == 'string')) {
4077 const GitHubStrategy = require('passport-github2');
4052 - passport.use(new GitHubStrategy({
4053 - clientID: domain.authstrategies.github.clientid,
4054 - clientSecret: domain.authstrategies.github.clientsecret,
4055 - callbackURL: url + 'auth-github-callback'
4056 - },
4078 + passport.use(new GitHubStrategy({ clientID: domain.authstrategies.github.clientid, clientSecret: domain.authstrategies.github.clientsecret, callbackURL: url + 'auth-github-callback' },
4079 function (token, tokenSecret, profile, cb) {
4080 var user = { id: 'user/' + domain.id + '/~github:' + profile.id, name: profile.displayName };
4081 if ((typeof profile.emails == 'object') && (profile.emails[0] != null) && (typeof profile.emails[0].value == 'string')) { user.email = profile.emails[0].value; }
@@ -4061,13 +4083,32 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
4083 }
4084 ));
4085 obj.app.get(url + 'auth-github', domain.passport.authenticate('github', { scope: ['user:email'] }));
4064 - obj.app.get(url + 'auth-github-callback',
4065 - domain.passport.authenticate('github', { failureRedirect: '/' }),
4066 - function (req, res) {
4067 - // Successful authentication, redirect home.
4068 - console.log('GitHub', req.session, req.user);
4069 - res.redirect('/');
4070 - });
4086 + obj.app.get(url + 'auth-github-callback', domain.passport.authenticate('github', { failureRedirect: '/' }), handleStrategyLogin);
4087 + }
4088 +
4089 + // Reddit
4090 + if ((typeof domain.authstrategies.reddit == 'object') && (typeof domain.authstrategies.reddit.clientid == 'string') && (typeof domain.authstrategies.reddit.clientsecret == 'string')) {
4091 + const RedditStrategy = require('passport-reddit');
4092 + passport.use(new RedditStrategy.Strategy({ clientID: domain.authstrategies.reddit.clientid, clientSecret: domain.authstrategies.reddit.clientsecret, callbackURL: url + 'auth-reddit-callback' },
4093 + function (token, tokenSecret, profile, cb) {
4094 + var user = { id: 'user/' + domain.id + '/~reddit:' + profile.id, name: profile.name };
4095 + if ((typeof profile.emails == 'object') && (profile.emails[0] != null) && (typeof profile.emails[0].value == 'string')) { user.email = profile.emails[0].value; }
4096 + return cb(null, user);
4097 + }
4098 + ));
4099 + obj.app.get(url + 'auth-reddit', function(req, res, next) {
4100 + domain.passport.authenticate('reddit', { state: 'rcookie', duration: 'permanent' })(req, res, next); // TODO: Replace 'rcookie' with a time-limited cookie
4101 + });
4102 + obj.app.get(url + 'auth-reddit-callback',
4103 + function(req, res, next) {
4104 + if (req.query.state == 'rcookie') {
4105 + delete req.session.rstate;
4106 + domain.passport.authenticate('reddit', { failureRedirect: '/' })(req, res, next);
4107 + } else {
4108 + delete req.session.rstate;
4109 + next(new Error(403));
4110 + }
4111 + }, handleStrategyLogin);
4112 }
4113 }
4114