From 13636d8bd908fca8fcd197a9813e02a134663fd7 Mon Sep 17 00:00:00 2001 From: pierre-lehnen-rc <55164754+pierre-lehnen-rc@users.noreply.github.com> Date: Tue, 21 Jul 2020 00:15:26 -0300 Subject: [PATCH] [FIX] SAML login saves invalid username when receiving multiple values (#18213) Co-authored-by: Diego Sampaio --- app/meteor-accounts-saml/server/lib/Utils.ts | 24 ++++++++-- .../tests/server.tests.ts | 46 +++++++++++++++++++ 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/app/meteor-accounts-saml/server/lib/Utils.ts b/app/meteor-accounts-saml/server/lib/Utils.ts index f0c22944036..3a76a4e6c65 100644 --- a/app/meteor-accounts-saml/server/lib/Utils.ts +++ b/app/meteor-accounts-saml/server/lib/Utils.ts @@ -326,7 +326,7 @@ export class SAMLUtils { return parsedMap; } - public static getProfileValue(profile: Record, mapping: IAttributeMapping): any { + public static getProfileValue(profile: Record, mapping: IAttributeMapping, forceString = false): any { const values: Record = { regex: '', }; @@ -334,10 +334,26 @@ export class SAMLUtils { let mainValue; for (const fieldName of fieldNames) { - values[fieldName] = profile[fieldName]; + let profileValue = profile[fieldName]; + + if (Array.isArray(profileValue)) { + for (let i = 0; i < profile[fieldName].length; i++) { + // Add every index to the list of possible values to be used, both first to last and from last to first + values[`${ fieldName }[${ i }]`] = profileValue[i]; + values[`${ fieldName }[-${ Math.abs(0 - profileValue.length + i) }]`] = profileValue[i]; + } + values[`${ fieldName }[]`] = profileValue.join(' '); + if (forceString) { + profileValue = profileValue.join(' '); + } + } else { + values[fieldName] = profileValue; + } + + values[fieldName] = profileValue; if (!mainValue) { - mainValue = profile[fieldName]; + mainValue = profileValue; } } @@ -422,7 +438,7 @@ export class SAMLUtils { } const email = this.getProfileValue(profile, userDataMap.email); - const profileUsername = this.getProfileValue(profile, userDataMap.username); + const profileUsername = this.getProfileValue(profile, userDataMap.username, true); const name = this.getProfileValue(profile, userDataMap.name); // Even if we're not using the email to identify the user, it is still mandatory because it's a mandatory information on Rocket.Chat diff --git a/app/meteor-accounts-saml/tests/server.tests.ts b/app/meteor-accounts-saml/tests/server.tests.ts index be8e26359c9..b806e2dd247 100644 --- a/app/meteor-accounts-saml/tests/server.tests.ts +++ b/app/meteor-accounts-saml/tests/server.tests.ts @@ -664,6 +664,22 @@ describe('SAML', () => { expect(userObject).to.have.property('customFields').that.is.a('Map').and.is.deep.equal(map); }); + it('should join array values if username receives an array of values', () => { + const { globalSettings } = SAMLUtils; + + const multipleUsernames = { + ...profile, + anotherUsername: ['user1', 'user2'], + }; + + SAMLUtils.updateGlobalSettings(globalSettings); + const userObject = SAMLUtils.mapProfileToUserObject(multipleUsernames); + + expect(userObject).to.be.an('object'); + expect(userObject).to.have.property('samlLogin').that.is.an('object'); + expect(userObject).to.have.property('username').that.is.equal('user1 user2'); + }); + // Channels support both a comma separated single value and an array of values it('should support `channels` attribute with multiple values', () => { const channelsProfile = { @@ -837,6 +853,36 @@ describe('SAML', () => { expect(userObject).to.have.property('fullName').that.is.equal('[DisplayName] (AnotherName)'); }); + it('should support individual array values on templates', () => { + const { globalSettings } = SAMLUtils; + + const multipleUsernames = { + ...profile, + anotherUsername: ['1', '2'], + }; + + const fieldMap = { + username: { + fieldName: 'anotherUsername', + template: 'user-__anotherUsername[-1]__', + }, + email: { + fieldName: 'anotherUsername', + template: 'user-__anotherUsername[0]__', + }, + }; + + globalSettings.userDataFieldMap = JSON.stringify(fieldMap); + + SAMLUtils.updateGlobalSettings(globalSettings); + const userObject = SAMLUtils.mapProfileToUserObject(multipleUsernames); + + expect(userObject).to.be.an('object'); + expect(userObject).to.have.property('username').that.is.equal('user-2'); + expect(userObject).to.have.property('emailList').that.is.an('array').that.includes('user-1'); + }); + + it('should collect the values of every attribute on the field map', () => { const { globalSettings } = SAMLUtils;