Added LDAP site admin support, OpenID samples and schema and more (#4506)

Ylian Saint-Hilaire committed Sep 6, 2022 at 00:30 UTC 1ae01b211385a9d2e8c4c6a05d4e5b0636d446d0
3 files changed +129 -79
meshcentral-config-schema.json
+21 -1
@@ -565,6 +565,11 @@
565 }
566 }
567 },
568 + "ldapSiteAdminGroups": {
569 + "type": [ "string", "array" ],
570 + "default": null,
571 + "description": "When set to a list of LDAP groups, users that are part of one of these groups will be set a site administrator, otherwise site administrator rights will be removed."
572 + },
573 "ldapUserRequiredGroupMembership": { "type": [ "string", "array" ], "default": null, "description": "A list of LDAP groups. Users must be part of at least one of these groups to allow login. If null, all users are allowed to login." },
574 "ldapOptions": { "type": "object", "description": "LDAP options passed to ldapauth-fork" },
575 "agentInviteCodes": { "type": "boolean", "default": false, "description": "Enabled a feature where you can set one or more invitation codes in a device group. You can then give a invitation link to users who can use it to download the agent." },
@@ -1210,7 +1215,22 @@
1215 "tokenURL": { "type": "string", "format": "uri", "description": "If set, this will be used as the token URL. (If set authorizationURL and userInfoURL need set also)" },
1216 "userInfoURL": { "type": "string", "format": "uri", "description": "If set, this will be used as the user info URL. (If set authorizationURL and tokenURL need set also)" },
1217 "logouturl": { "type": "string", "format": "uri", "description": "Then set, the user will be redirected to this URL when hitting the logout link." },
1213 - "newAccounts": { "type": "boolean", "default": true }
1218 + "newAccounts": { "type": "boolean", "default": true },
1219 + "groups": {
1220 + "type": "object",
1221 + "properties": {
1222 + "required": { "type": [ "string", "array" ], "description": "When set, the user must be part of one of the OIDC user groups to login to MeshCentral." },
1223 + "siteadmin": { "type": [ "string", "array" ], "description": "When set, users part of these groups will be promoted with site administrator in MeshCentral, users that are not part of these groups will be demoted." },
1224 + "sync": {
1225 + "type": [ "boolean", "object" ],
1226 + "description": "Allows some or all ODIC user groups to be mirrored within MeshCentral as user groups.",
1227 + "properties": {
1228 + "enabled": { "type": "boolean", "default": false },
1229 + "filter": { "type": [ "string", "array" ], "description": "When set, limits what OIDC groups are mirrored into MeshCentral user groups." }
1230 + }
1231 + }
1232 + }
1233 + }
1234 },
1235 "required": [ "issuer", "clientid", "clientsecret", "callbackURL" ]
1236 }
sample-config-advanced.json
+10 -1
@@ -520,7 +520,15 @@
520 "tokenURL": "https://sso.server.com/api/oidc/token",
521 "userInfoURL": "https://sso.server.com/api/oidc/userinfo",
522 "logoutURL": "https://sso.server.com/logout",
523 - "newAccounts": true
523 + "newAccounts": true,
524 + "groups": {
525 + "required": [ "groupA", "groupB", "groupC" ],
526 + "siteadmin": [ "groupA" ],
527 + "sync": {
528 + "enable": true,
529 + "filter": [ "groupB", "groupC" ]
530 + }
531 + }
532 }
533 }
534 },
@@ -535,6 +543,7 @@
543 "_LDAPUserKey": "uid",
544 "_LDAPUserEmail": "otherMail",
545 "_LDAPUserGroups": "memberOf",
546 + "_LDAPSiteAdminGroups": [ "CN=Domain Admins,CN=Users,DC=sample,DC=com" ],
547 "_LDAPUserRequiredGroupMembership": [ "CN=Domain Admins,CN=Users,DC=sample,DC=com" ],
548 "_LDAPSyncWithUserGroups": { "filter": [ "CN=Domain Admins" ] },
549 "_LDAPOptions": {
webserver.js
+98 -77
@@ -478,12 +478,22 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
478 if (Array.isArray(userMemberships) == false) { userMemberships = []; }
479
480 // See if the user is required to be part of an LDAP user group in order to log into this server.
481 - if (typeof domain.ldapuserrequiredgroupmembership == 'string') { domain.ldapuserrequiredgroupmembership = [domain.ldapuserrequiredgroupmembership]; }
482 - if (Array.isArray(domain.ldapuserrequiredgroupmembership) && (domain.ldapuserrequiredgroupmembership.length > 0)) {
481 + if (typeof domain.ldapuserrequiredgroupmembership == 'string') { domain.ldapuserrequiredgroupmembership = [ domain.ldapuserrequiredgroupmembership ]; }
482 + if (Array.isArray(domain.ldapuserrequiredgroupmembership)) {
483 // Look for a matching LDAP user group
484 var userMembershipMatch = false;
485 for (var i in domain.ldapuserrequiredgroupmembership) { if (userMemberships.indexOf(domain.ldapuserrequiredgroupmembership[i]) >= 0) { userMembershipMatch = true; } }
486 - if (userMembershipMatch === false) { parent.debug('ldap', 'Denying login to a user that is not a member of a LDAP required group.'); fn('denied'); return; } // If there is no match, deny the login
486 + if (userMembershipMatch === false) { parent.debug('authlog', 'LDAP denying login to a user that is not a member of a LDAP required group.'); fn('denied'); return; } // If there is no match, deny the login
487 + }
488 +
489 + // Check if user is in an site administrator group
490 + var siteAdminGroup = null;
491 + if (typeof domain.ldapsiteadmingroups == 'string') { domain.ldapsiteadmingroups = [ domain.ldapsiteadmingroups ]; }
492 + if (Array.isArray(domain.ldapsiteadmingroups)) {
493 + siteAdminGroup = false;
494 + for (var i in domain.ldapsiteadmingroups) {
495 + if (userMemberships.indexOf(domain.ldapsiteadmingroups[i]) >= 0) { siteAdminGroup = domain.ldapsiteadmingroups[i]; }
496 + }
497 }
498
499 // See if we need to sync LDAP user memberships with user groups
@@ -538,7 +548,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
548 }
549
550 // Display user information extracted from LDAP data
541 - parent.debug('ldap', 'User login, id: ' + shortname + ', username: ' + username + ', email: ' + email + ', realname: ' + realname + ', phone: ' + phonenumber + ', image: ' + (userimage != null));
551 + parent.debug('authlog', 'LDAP user login, id: ' + shortname + ', username: ' + username + ', email: ' + email + ', realname: ' + realname + ', phone: ' + phonenumber + ', image: ' + (userimage != null));
552
553 // If there is a testing userid, use that
554 if (ldapHandlerFunc.ldapShortName) {
@@ -596,6 +606,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
606 // Indicate that this user has a image
607 if (userimage != null) { user.flags = 1; }
608
609 + // See if the user is a member of the site admin group.
610 + if (typeof siteAdminGroup === 'string') {
611 + parent.debug('authlog', `LDAP: Granting site admin privilages to new user "${user.name}" found in admin group: ${siteAdminGroup}`);
612 + user.siteadmin = 0xFFFFFFFF;
613 + }
614 +
615 // Sync the user with LDAP matching user groups
616 if (syncExternalUserGroups(domain, user, userMemberships, 'ldap') == true) { userChanged = true; }
617
@@ -633,6 +649,17 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
649 if ((userimage != null) && ((user.flags == null) || ((user.flags & 1) == 0))) { if (user.flags == null) { user.flags = 1; } else { user.flags += 1; } userChanged = true; }
650 if ((userimage == null) && (user.flags != null) && ((user.flags & 1) != 0)) { if (user.flags == 1) { delete user.flags; } else { user.flags -= 1; } userChanged = true; }
651
652 + // See if the user is a member of the site admin group.
653 + if ((typeof siteAdminGroup === 'string') && (user.siteadmin !== 0xFFFFFFFF)) {
654 + parent.debug('authlog', `LDAP: Granting site admin privilages to user "${user.name}" found in administrator group: ${siteAdminGroup}`);
655 + user.siteadmin = 0xFFFFFFFF;
656 + userChanged = true;
657 + } else if ((siteAdminGroup === false) && (user.siteadmin === 0xFFFFFFFF)) {
658 + parent.debug('authlog', `LDAP: Remoking site admin privilages to user "${user.name}" since they are not found in any administrator groups.`);
659 + delete user.siteadmin;
660 + userChanged = true;
661 + }
662 +
663 // Synd the user with LDAP matching user groups
664 if (syncExternalUserGroups(domain, user, userMemberships, 'ldap') == true) { userChanged = true; }
665
@@ -2494,68 +2521,61 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
2521 const domain = checkUserIpAddress(req, res);
2522 const authStrategy = req.user.strategy
2523 if (domain == null) { return; }
2497 - parent.debug(authStrategy, 'handleStrategyLogin: ' + JSON.stringify(req.user));
2524 + parent.debug('authlog', `${authStrategy} - Login: ` + JSON.stringify(req.user));
2525 if ((req.user != null) && (req.user.sid != null)) {
2526
2527 // Check if any group related options exist
2501 - if (typeof domain.authstrategies[authStrategy].groups !== 'undefined' && domain.authstrategies[authStrategy].groups !== null) {
2502 - if (typeof req.user.groups !== 'undefined' && req.user.groups !== null) { var userMemberships = req.user.groups; }
2503 - if (typeof userMemberships == 'string') { userMemberships = [userMemberships]; }
2504 - if (Array.isArray(userMemberships) == false) { userMemberships = []; }
2505 - parent.debug(authStrategy, `Groups: Reported User Memberships from IdP: ${userMemberships.join(', ')}`);
2528 + var userMemberships = [];
2529 + var siteAdminGroup = null;
2530 + if (typeof domain.authstrategies[authStrategy].groups === 'object') {
2531 + if (Array.isArray(req.user.groups)) { userMemberships = req.user.groups; }
2532 + else if (typeof req.user.groups == 'string') { userMemberships = [req.user.groups]; }
2533 + parent.debug('authlog', `${authStrategy}: User login with reported memberships from IdP: ${userMemberships.join(', ')}`);
2534
2535 // See if the user is required to be part of a specific group in order to log into this server.
2508 - if (typeof domain.authstrategies[authStrategy].groups.required !== 'undefined' && domain.authstrategies[authStrategy].groups.required !== null){
2509 - if (typeof domain.authstrategies[authStrategy].groups.required == 'string') { domain.authstrategies[authStrategy].groups.required = [domain.authstrategies[authStrategy].groups.required]; }
2510 - if (Array.isArray(domain.authstrategies[authStrategy].groups.required) && (domain.authstrategies[authStrategy].groups.required.length > 0)) {
2511 - var userMembershipMatch = false;
2512 - for (var i in domain.authstrategies[authStrategy].groups.required) {
2513 - if (userMemberships.indexOf(domain.authstrategies[authStrategy].groups.required[i]) >= 0) {
2514 - userMembershipMatch = true;
2515 - parent.debug(authStrategy, `Groups: User found in required group: ${domain.authstrategies[authStrategy].groups.required[i]}`);
2516 - }
2536 + if (typeof domain.authstrategies[authStrategy].groups.required == 'string') { domain.authstrategies[authStrategy].groups.required = [domain.authstrategies[authStrategy].groups.required]; }
2537 + if (Array.isArray(domain.authstrategies[authStrategy].groups.required)) {
2538 + var userMembershipMatch = false;
2539 + for (var i in domain.authstrategies[authStrategy].groups.required) {
2540 + if (userMemberships.indexOf(domain.authstrategies[authStrategy].groups.required[i]) >= 0) {
2541 + userMembershipMatch = true;
2542 + parent.debug('authlog', `${authStrategy}: Login user found in required group: ${domain.authstrategies[authStrategy].groups.required[i]}`);
2543 }
2518 - if (userMembershipMatch === false) { parent.debug(authStrategy, 'Groups: DENIED - User not found in required group.'); fn('denied'); return;}
2544 }
2545 + if (userMembershipMatch === false) { parent.debug('authlog', `${authStrategy}: User login denied. User not found in required group.`); fn('denied'); return;}
2546 }
2547
2522 - // Check if user is in admin group
2523 - var siteadminGroup = false
2524 - if (typeof domain.authstrategies[authStrategy].groups.siteadmin !== 'undefined' && domain.authstrategies[authStrategy].groups.siteadmin !== null) {
2525 - if (typeof domain.authstrategies[authStrategy].groups.siteadmin == 'string') { domain.authstrategies[authStrategy].groups.siteadmin = [domain.authstrategies[authStrategy].groups.siteadmin]; }
2526 - if (Array.isArray(domain.authstrategies[authStrategy].groups.siteadmin) && (domain.authstrategies[authStrategy].groups.siteadmin.length > 0)) {
2527 - for (var i in domain.authstrategies[authStrategy].groups.siteadmin) {
2528 - if (userMemberships.indexOf(domain.authstrategies[authStrategy].groups.siteadmin[i]) >= 0) {
2529 - siteadminGroup = true;
2530 - }
2531 - }
2548 + // Check if user is in an administrator group
2549 + if (typeof domain.authstrategies[authStrategy].groups.siteadmin == 'string') { domain.authstrategies[authStrategy].groups.siteadmin = [ domain.authstrategies[authStrategy].groups.siteadmin ]; }
2550 + if (Array.isArray(domain.authstrategies[authStrategy].groups.siteadmin)) {
2551 + siteAdminGroup = false;
2552 + for (var i in domain.authstrategies[authStrategy].groups.siteadmin) {
2553 + if (userMemberships.indexOf(domain.authstrategies[authStrategy].groups.siteadmin[i]) >= 0) { siteAdminGroup = domain.authstrategies[authStrategy].groups.siteadmin[i]; }
2554 }
2555 }
2556
2557 // See if we need to sync user-memberships (IdP) with user-groups (meshcentral)
2536 - if (domain.authstrategies[authStrategy].groups.sync.enabled === true || domain.authstrategies[authStrategy].groups.sync === true) {
2537 - if (domain.authstrategies[authStrategy].groups.sync === true) { domain.authstrategies[authStrategy].groups.sync = {"enabled":true}; }
2538 - if (typeof domain.authstrategies[authStrategy].groups.sync.filter !== 'undefined' && domain.authstrategies[authStrategy].groups.sync.filter !== null) {
2539 - const filteredMemberships = [];
2540 - if (typeof domain.authstrategies[authStrategy].groups.sync.filter == 'string') { domain.authstrategies[authStrategy].groups.sync.filter = [domain.authstrategies[authStrategy].groups.sync.filter]; }
2541 - if (Array.isArray(domain.authstrategies[authStrategy].groups.sync.filter)) {
2542 - for (var i in userMemberships) {
2543 - for (var j in domain.authstrategies[authStrategy].groups.sync.filter) {
2544 - if (userMemberships[i].indexOf(domain.authstrategies[authStrategy].groups.sync.filter[j]) >= 0) { filteredMemberships.push(userMemberships[i]); }
2545 - }
2546 - }
2547 - }
2548 - if (Array.isArray(filteredMemberships)) {
2549 - if (filteredMemberships.length > 0) {
2550 - parent.debug(authStrategy, `Groups: Filtered user memberships from config: ${filteredMemberships.join(', ')}`);
2558 + if (domain.authstrategies[authStrategy].groups.sync === true) { domain.authstrategies[authStrategy].groups.sync = { enabled: true }; }
2559 + if ((typeof domain.authstrategies[authStrategy].groups.sync == 'object') && (domain.authstrategies[authStrategy].groups.sync.enabled == true)) {
2560 + if (typeof domain.authstrategies[authStrategy].groups.sync.filter == 'string') { domain.authstrategies[authStrategy].groups.sync.filter = [ domain.authstrategies[authStrategy].groups.sync.filter ]; }
2561 + const filteredMemberships = [];
2562 + if (Array.isArray(domain.authstrategies[authStrategy].groups.sync.filter)) {
2563 + for (var i in userMemberships) {
2564 + for (var j in domain.authstrategies[authStrategy].groups.sync.filter) {
2565 + if (userMemberships[i].indexOf(domain.authstrategies[authStrategy].groups.sync.filter[j]) >= 0) { filteredMemberships.push(userMemberships[i]); }
2566 }
2552 - } else {
2553 - parent.debug(authStrategy, `Groups: No groups found with filter: ${domain.authstrategies[authStrategy].groups.sync.filter.join(', ')}`);
2567 }
2555 - userMemberships = filteredMemberships;
2568 }
2569 + if (filteredMemberships.length > 0) {
2570 + parent.debug('authlog', `${authStrategy}: Filtered user memberships from config: ${filteredMemberships.join(', ')}`);
2571 + } else {
2572 + parent.debug('authlog', `${authStrategy}: No groups found with filter: ${domain.authstrategies[authStrategy].groups.sync.filter.join(', ')}`);
2573 + }
2574 + userMemberships = filteredMemberships;
2575 }
2576 }
2577 +
2578 + // Check if the user already exists
2579 const userid = 'user/' + domain.id + '/' + req.user.sid;
2580 var user = obj.users[userid];
2581 if (user == null) {
@@ -2572,7 +2592,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
2592
2593 if (newAccountAllowed === true) {
2594 // Create the user
2575 - parent.debug(authStrategy, 'handleStrategyLogin: creating new user: ' + userid);
2595 + parent.debug('authlog', `${authStrategy}: Creating new login user: "${userid}"`);
2596 user = { type: 'user', _id: userid, name: req.user.name, email: req.user.email, creation: Math.floor(Date.now() / 1000), login: Math.floor(Date.now() / 1000), access: Math.floor(Date.now() / 1000), domain: domain.id };
2597 if (req.user.email != null) { user.email = req.user.email; user.emailVerified = true; }
2598 if (domain.newaccountsrights) { user.siteadmin = domain.newaccountsrights; } // New accounts automatically assigned server rights.
@@ -2606,15 +2626,15 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
2626 }
2627 }
2628
2609 -
2610 - // Sync the user groups if enabled
2611 - if (domain.authstrategies[authStrategy].groups.sync.enabled === true) { syncExternalUserGroups(domain, user, userMemberships, authStrategy) }
2629 + if (typeof domain.authstrategies[authStrategy].groups == 'object') {
2630 + // Sync the user groups if enabled
2631 + if ((typeof domain.authstrategies[authStrategy].groups.sync == 'object') && (domain.authstrategies[authStrategy].groups.sync.enabled === true)) { syncExternalUserGroups(domain, user, userMemberships, authStrategy) }
2632
2613 - // See if the user is a member of the site admin group.
2614 - if (typeof domain.authstrategies[authStrategy].groups.siteadmin !== 'undefined' && domain.authstrategies[authStrategy].groups.siteadmin !== null)
2615 - if (siteadminGroup === true && user.siteadmin != 4294967295) {
2616 - parent.debug(authStrategy, `Groups: GRANTING ADMIN PRIVLEGE - User found in admin group: ${domain.authstrategies[authStrategy].groups.siteadmin[i]}`);
2617 - user.siteadmin = 4294967295;
2633 + // See if the user is a member of the site admin group.
2634 + if (typeof siteAdminGroup === 'string') {
2635 + parent.debug('authlog', `${authStrategy}: Granting site admin privilages to new user "${user.name}" found in admin group: ${siteAdminGroup}`);
2636 + user.siteadmin = 0xFFFFFFFF;
2637 + }
2638 }
2639
2640 // Save the user
@@ -2637,7 +2657,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
2657 obj.parent.DispatchEvent(targets, obj, loginEvent);
2658 } else {
2659 // New users not allowed
2640 - parent.debug(authStrategy, 'handleStrategyLogin: Can\'t create new accounts');
2660 + parent.debug('authlog', `${authStrategy}: Can\'t create new user, account creation is not allowed`);
2661 req.session.loginmode = 1;
2662 req.session.messageid = 100; // Unable to create account.
2663 res.redirect(domain.url + getQueryPortion(req));
@@ -2653,14 +2673,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
2673 if (domain.authstrategies[authStrategy].groups.sync.enabled === true) { syncExternalUserGroups(domain, user, userMemberships, authStrategy) }
2674
2675 // See if the user is a member of the site admin group.
2656 - if (typeof domain.authstrategies[authStrategy].groups.siteadmin !== 'undefined' && domain.authstrategies[authStrategy].groups.siteadmin !== null) {
2657 - if (siteadminGroup === true && user.siteadmin != 4294967295) {
2658 - parent.debug(authStrategy, 'Groups: GRANTING ADMIN PRIVLEGE - User found in admin group.');
2659 - user.siteadmin = 4294967295;
2676 + if ((typeof domain.authstrategies[authStrategy].groups.siteadmin !== 'undefined') && (domain.authstrategies[authStrategy].groups.siteadmin !== null)) {
2677 + if ((typeof siteAdminGroup === 'string') && (user.siteadmin !== 0xFFFFFFFF)) {
2678 + parent.debug('authlog', `${authStrategy}: Granting site admin privilages to user "${user.name}" found in administrator group: ${siteAdminGroup}`);
2679 + user.siteadmin = 0xFFFFFFFF;
2680 userChanged = true;
2661 - } else if (siteadminGroup === false && user.siteadmin == 4294967295) {
2662 - parent.debug(authStrategy, 'Groups: REVOKING ADMIN PRIVLEGE - User NOT found in admin group!');
2663 - user.siteadmin = null;
2681 + } else if ((siteAdminGroup === false) && (user.siteadmin === 0xFFFFFFFF)) {
2682 + parent.debug('authlog', `${authStrategy}: Remoking site admin privilages to user "${user.name}" since they are not found in any administrator groups.`);
2683 + delete user.siteadmin;
2684 userChanged = true;
2685 }
2686 }
@@ -2675,7 +2695,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
2695 if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to create the user. Another event will come.
2696 parent.DispatchEvent(targets, obj, event);
2697 }
2678 - parent.debug(authStrategy, 'handleStrategyLogin: succesful login: ' + userid);
2698 + parent.debug('authlog', `${authStrategy}: succesful login: ${userid}`);
2699 req.session.userid = userid;
2700 setSessionRandom(req);
2701
@@ -6986,33 +7006,33 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
7006 // Generic OpenID Connect
7007 if ((typeof domain.authstrategies.oidc == 'object') && (typeof domain.authstrategies.oidc.clientid == 'string') && (typeof domain.authstrategies.oidc.clientsecret == 'string') && (typeof domain.authstrategies.oidc.issuer == 'string')) {
7008 const OIDCStrategy = require('@mstrhakr/passport-openidconnect');
6989 - var options = {
7009 + const options = {
7010 issuer: domain.authstrategies.oidc.issuer,
7011 clientID: domain.authstrategies.oidc.clientid,
7012 clientSecret: domain.authstrategies.oidc.clientsecret,
7013 scope: ['profile', 'email', 'groups'],
7014 };
6995 - async function discoverOptions(options){
7015 + const discoverOptions = async function(options){
7016 if ((typeof domain.authstrategies.oidc.authorizationurl != 'string') || (typeof domain.authstrategies.oidc.tokenurl != 'string') || (typeof domain.authstrategies.oidc.userinfourl != 'string')) {
7017 const Issuer = require('openid-client').Issuer;
6998 - parent.debug('oidc', 'Attempting to discover well known endpoints for ' + options.issuer);
7018 + parent.debug('authlog', 'OpenID: Attempting to discover well known endpoints for ' + options.issuer);
7019 var issuer = await Issuer.discover(options.issuer)
7020 if (typeof domain.authstrategies.oidc.authorizationurl == 'string') { options.authorizationURL = domain.authstrategies.oidc.authorizationurl; } else { options.authorizationURL = issuer.metadata.authorization_endpoint; }
7021 if (typeof domain.authstrategies.oidc.tokenurl == 'string') { options.tokenURL = domain.authstrategies.oidc.tokenurl; } else { options.tokenURL = issuer.metadata.token_endpoint; }
7022 if (typeof domain.authstrategies.oidc.userinfourl == 'string') { options.userInfoURL = domain.authstrategies.oidc.userinfourl; } else { options.userInfoURL = issuer.metadata.userinfo_endpoint; }
7023 if (typeof domain.authstrategies.oidc.callbackurl == 'string') { options.callbackURL = domain.authstrategies.oidc.callbackurl; } else { options.callbackURL = url + 'oidc-callback'; }
7004 - parent.debug('oidc', 'Discovered ' + JSON.stringify(options));
7024 + parent.debug('authlog', 'OpenID: Discovered ' + JSON.stringify(options));
7025 }
7026 return options;
7027 }
7008 - discoverOptions(options).then((options)=>{
7028 + discoverOptions(options).then(function(options) {
7029 passport.use('oidc-' + domain.id, new OIDCStrategy.Strategy(options,
7030 function verify(issuer, profile, verified) {
7011 - parent.debug('oidc', 'Connecting to ' + issuer + ' with the following options ' + JSON.stringify(options));
7031 + parent.debug('authlog', `OpenID: Connecting to ${issuer} with the following options ` + JSON.stringify(options));
7032 var user = { sid: '~oidc:' + profile.id, name: profile.displayName, strategy: 'oidc' };
7033 if ( Array.isArray(profile.emails[0].value) ) { user.email = profile.emails[0].value[0]; } else { user.email = profile.emails[0].value; }
7034 if ( Array.isArray(profile.groups[0].value) ) { user.groups = profile.groups[0].value; } else { user.groups = [profile.groups[0].value]; }
7015 - parent.debug('oidc', `Configured: User: ${JSON.stringify(user)} FROM Profile: ${JSON.stringify(profile)}`);
7035 + parent.debug('authlog', `OpenID: Configured: User: ${JSON.stringify(user)} FROM Profile: ${JSON.stringify(profile)}`);
7036 return verified(null, user);
7037 }
7038 ))
@@ -8916,7 +8936,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
8936 function syncExternalUserGroups(domain, user, userMemberships, userMembershipType) {
8937 var userChanged = false;
8938 if (user.links == null) { user.links = {}; }
8919 - var authType = userMembershipType
8939 +
8940 // Create a user of memberships for this user that type
8941 var existingUserMemberships = {};
8942 for (var i in user.links) {
@@ -8930,7 +8950,6 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
8950 var ugrp = obj.userGroups[ugrpid];
8951 if (ugrp == null) {
8952 // This user group does not exist, create it
8933 - parent.debug(authType, 'Creating new ' + authType + ' user group ' + userMemberships[i] + '.');
8953 ugrp = { type: 'ugrp', _id: ugrpid, name: membership, domain: domain.id, membershipType: userMembershipType, links: {} };
8954
8955 // Save the new group
@@ -8947,7 +8966,6 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
8966
8967 if (existingUserMemberships[ugrpid] == null) {
8968 // This user is not part of the user group, add it.
8950 - parent.debug(authType, 'Adding ' + user.name + ' to ' + authType + ' user group ' + userMemberships[i] + '.');
8969 if (user.links == null) { user.links = {}; }
8970 user.links[ugrp._id] = { rights: 1 };
8971 userChanged = true;
@@ -8968,6 +8986,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
8986 var event = { etype: 'ugrp', userid: user._id, username: user.name, ugrpid: ugrp._id, name: ugrp.name, desc: ugrp.desc, action: 'usergroupchange', links: ugrp.links, msgid: 71, msgArgs: [user.name, ugrp.name], msg: 'Added user(s) ' + user.name + ' to user group ' + ugrp.name, addUserDomain: domain.id };
8987 if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user group. Another event will come.
8988 parent.DispatchEvent(['*', ugrp._id, user._id], obj, event);
8989 +
8990 + // Log in the auth log
8991 + parent.authLog('https', 'Adding ' + user.name + ' to ' + userMembershipType + ' user group ' + userMemberships[i] + '.');
8992 } else {
8993 // User is already part of this user group
8994 delete existingUserMemberships[ugrpid];
@@ -8977,7 +8998,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
8998 // Remove the user from any memberships they don't belong to anymore
8999 for (var ugrpid in existingUserMemberships) {
9000 var ugrp = obj.userGroups[ugrpid];
8980 - parent.debug(authType, 'Removing ' + user.name + ' from ' + authType + ' user group ' + ugrp.name + '.');
9001 + parent.authLog('https', 'Removing ' + user.name + ' from ' + userMembershipType + ' user group ' + ugrp.name + '.');
9002 if ((user.links != null) && (user.links[ugrpid] != null)) {
9003 delete user.links[ugrpid];
9004