diff --git a/app/meteor-accounts-saml/server/saml_rocketchat.js b/app/meteor-accounts-saml/server/saml_rocketchat.js index 2ee0e2fe05643..b69f33cbe3514 100644 --- a/app/meteor-accounts-saml/server/saml_rocketchat.js +++ b/app/meteor-accounts-saml/server/saml_rocketchat.js @@ -85,12 +85,44 @@ Meteor.methods({ section: name, i18nLabel: 'Accounts_OAuth_Custom_Button_Color', }); + settings.add(`SAML_Custom_${ name }_email_field`, 'email', { + type: 'string', + group: 'SAML', + section: name, + i18nLabel: 'SAML_Custom_EMail_Field', + }); + settings.add(`SAML_Custom_${ name }_username_field`, 'username', { + type: 'string', + group: 'SAML', + section: name, + i18nLabel: 'SAML_Custom_Username_Field', + }); settings.add(`SAML_Custom_${ name }_generate_username`, false, { type: 'boolean', group: 'SAML', section: name, i18nLabel: 'SAML_Custom_Generate_Username', }); + settings.add(`SAML_Custom_${ name }_username_normalize`, 'None', { + type: 'select', + values: [ + { key: 'None', i18nLabel: 'SAML_Custom_Username_Normalize_None' }, + { key: 'Lowercase', i18nLabel: 'SAML_Custom_Username_Normalize_Lowercase' }, + ], + group: 'SAML', + section: name, + i18nLabel: 'SAML_Custom_Username_Normalize', + }); + settings.add(`SAML_Custom_${ name }_immutable_property`, 'EMail', { + type: 'select', + values: [ + { key: 'Username', i18nLabel: 'SAML_Custom_Immutable_Property_Username' }, + { key: 'EMail', i18nLabel: 'SAML_Custom_Immutable_Property_EMail' }, + ], + group: 'SAML', + section: name, + i18nLabel: 'SAML_Custom_Immutable_Property', + }); settings.add(`SAML_Custom_${ name }_debug`, false, { type: 'boolean', group: 'SAML', @@ -140,6 +172,10 @@ const getSamlConfigs = function(service) { }, entryPoint: settings.get(`${ service.key }_entry_point`), idpSLORedirectURL: settings.get(`${ service.key }_idp_slo_redirect_url`), + usernameField: settings.get(`${ service.key }_username_field`), + usernameNormalize: settings.get(`${ service.key }_username_normalize`), + emailField: settings.get(`${ service.key }_email_field`), + immutableProperty: settings.get(`${ service.key }_immutable_property`), generateUsername: settings.get(`${ service.key }_generate_username`), debug: settings.get(`${ service.key }_debug`), nameOverwrite : settings.get(`${ service.key }_name_overwrite`), @@ -179,6 +215,10 @@ const configureSamlService = function(samlConfigs) { Accounts.saml.settings.generateUsername = samlConfigs.generateUsername; Accounts.saml.settings.nameOverwrite = samlConfigs.nameOverwrite; Accounts.saml.settings.mailOverwrite = samlConfigs.mailOverwrite; + Accounts.saml.settings.immutableProperty = samlConfigs.immutableProperty; + Accounts.saml.settings.emailField = samlConfigs.emailField; + Accounts.saml.settings.usernameField = samlConfigs.usernameField; + Accounts.saml.settings.usernameNormalize = samlConfigs.usernameNormalize; Accounts.saml.settings.debug = samlConfigs.debug; return { diff --git a/app/meteor-accounts-saml/server/saml_server.js b/app/meteor-accounts-saml/server/saml_server.js index db5699fe334ec..1f192ec1f8397 100644 --- a/app/meteor-accounts-saml/server/saml_server.js +++ b/app/meteor-accounts-saml/server/saml_server.js @@ -93,6 +93,16 @@ Meteor.methods({ }, }); +Accounts.normalizeUsername = function(name) { + switch (Accounts.saml.settings.usernameNormalize) { + case 'Lowercase': + name = name.toLowerCase(); + break; + } + + return name; +}; + Accounts.registerLoginHandler(function(loginRequest) { if (!loginRequest.saml || !loginRequest.credentialToken) { return undefined; @@ -110,8 +120,10 @@ Accounts.registerLoginHandler(function(loginRequest) { }; } + const { emailField, usernameField } = Accounts.saml.settings; + if (loginResult && loginResult.profile && loginResult.profile.email) { - const emailList = Array.isArray(loginResult.profile.email) ? loginResult.profile.email : [loginResult.profile.email]; + const emailList = Array.isArray(loginResult.profile[emailField]) ? loginResult.profile[emailField] : [loginResult.profile[emailField]]; const emailRegex = new RegExp(emailList.map((email) => `^${ RegExp.escape(email) }$`).join('|'), 'i'); const eduPersonPrincipalName = loginResult.profile.eppn; @@ -128,32 +140,44 @@ Accounts.registerLoginHandler(function(loginRequest) { eppnMatch = true; } + let username; + if (loginResult.profile[usernameField]) { + username = Accounts.normalizeUsername(loginResult.profile[usernameField]); + } + // If eppn is not exist if (!user) { - user = Meteor.users.findOne({ - 'emails.address': emailRegex, - }); + if (Accounts.saml.settings.immutableProperty === 'Username') { + user = Meteor.users.findOne({ + username, + }); + } else { + user = Meteor.users.findOne({ + 'emails.address': emailRegex, + }); + } } + const emails = emailList.map((email) => ({ + address: email, + verified: true, + })); + if (!user) { const newUser = { name: fullName, active: true, eppn: eduPersonPrincipalName, globalRoles: ['user'], - emails: emailList.map((email) => ({ - address: email, - verified: true, - })), + emails, }; if (Accounts.saml.settings.generateUsername === true) { - const username = generateUsernameSuggestion(newUser); - if (username) { - newUser.username = username; - } - } else if (loginResult.profile.username) { - newUser.username = loginResult.profile.username; + username = generateUsernameSuggestion(newUser); + } + + if (username) { + newUser.username = username; } const userId = Accounts.insertUserDoc({}, newUser); @@ -192,6 +216,8 @@ Accounts.registerLoginHandler(function(loginRequest) { $set: { // TBD this should be pushed, otherwise we're only able to SSO into a single IDP at a time 'services.saml': samlLogin, + username, + emails, }, }); diff --git a/packages/rocketchat-i18n/i18n/de.i18n.json b/packages/rocketchat-i18n/i18n/de.i18n.json index e335b0e63c1ba..9f4aa86edc826 100644 --- a/packages/rocketchat-i18n/i18n/de.i18n.json +++ b/packages/rocketchat-i18n/i18n/de.i18n.json @@ -2543,6 +2543,14 @@ "SAML_Custom_Logout_Behaviour_Terminate_SAML_Session": "SAML-Session beenden", "SAML_Custom_Private_Key": "Privater Schlüssel", "SAML_Custom_Provider": "Benutzerdefinierter Provider", + "SAML_Custom_EMail_Field": "E-Mail Feldname", + "SAML_Custom_Username_Field": "Username Feldname", + "SAML_Custom_Username_Normalize": "Benutzername normalisierung", + "SAML_Custom_Username_Normalize_None": "Keine normalisierung", + "SAML_Custom_Username_Normalize_Lowercase": "Zu Kleinschreibung", + "SAML_Custom_Immutable_Property": "Unveränderbares Feld", + "SAML_Custom_Immutable_Property_Username": "Benutzername", + "SAML_Custom_Immutable_Property_EMail": "E-Mail", "SAML_Custom_Public_Cert": "Öffentliches Zertifikat", "Saturday": "Samstag", "Save": "Speichern", diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index e4f6eba924157..c10bf609c64aa 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -2547,6 +2547,14 @@ "SAML_Custom_Logout_Behaviour_Terminate_SAML_Session": "Terminate SAML-session", "SAML_Custom_Private_Key": "Private Key Contents", "SAML_Custom_Provider": "Custom Provider", + "SAML_Custom_EMail_Field": "E-Mail field name", + "SAML_Custom_Username_Field": "Username field name", + "SAML_Custom_Username_Normalize": "Normalize username", + "SAML_Custom_Username_Normalize_None": "No normalization", + "SAML_Custom_Username_Normalize_Lowercase": "To Lowercase", + "SAML_Custom_Immutable_Property": "Immutable field name", + "SAML_Custom_Immutable_Property_Username": "Username", + "SAML_Custom_Immutable_Property_EMail": "E-Mail", "SAML_Custom_Public_Cert": "Public Cert Contents", "Saturday": "Saturday", "Save": "Save",