diff --git a/server/modules/authentication/saml/authentication.js b/server/modules/authentication/saml/authentication.js index 6eeef27a80..1324890793 100644 --- a/server/modules/authentication/saml/authentication.js +++ b/server/modules/authentication/saml/authentication.js @@ -56,6 +56,26 @@ module.exports = { picture: _.get(profile, conf.mappingPicture, '') } }) + + // map users provider groups to wiki groups with the same name, and remove any groups that don't match + // Code copied from the LDAP implementation with a slight variation on the field we extract the value from + // In SAML v2 groups come in profile.attributes and can be 1 string or an array of strings + if (conf.mapGroups) { + const maybeArrayOfGroups = _.get(profile.attributes, conf.mappingGroups) + const groups = (maybeArrayOfGroups && !_.isArray(maybeArrayOfGroups)) ? [maybeArrayOfGroups] : maybeArrayOfGroups + + if (groups && _.isArray(groups)) { + const currentGroups = (await user.$relatedQuery('groups').select('groups.id')).map(g => g.id) + const expectedGroups = Object.values(WIKI.auth.groups).filter(g => groups.includes(g.name)).map(g => g.id) + for (const groupId of _.difference(expectedGroups, currentGroups)) { + await user.$relatedQuery('groups').relate(groupId) + } + for (const groupId of _.difference(currentGroups, expectedGroups)) { + await user.$relatedQuery('groups').unrelate().where('groupId', groupId) + } + } + } + cb(null, user) } catch (err) { cb(err, null) diff --git a/server/modules/authentication/saml/definition.yml b/server/modules/authentication/saml/definition.yml index bfb24d15ff..c39dd73125 100644 --- a/server/modules/authentication/saml/definition.yml +++ b/server/modules/authentication/saml/definition.yml @@ -162,3 +162,15 @@ props: default: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/picture' hint: The field storing the user avatar picture. Can be a variable name or a URI-formatted string. order: 43 + mapGroups: + type: Boolean + title: Map Groups + hint: Map groups matching names from the provider user groups. User Groups Field Mapping must also be defined for this to work. Note this will remove any groups the user has that doesn't match any group from the provider. + default: false + order: 44 + mappingGroups: + title: User Groups Field Mapping + type: String + default: 'memberOf' + hint: The field storing the user groups attribute (when Map Groups is enabled). Can be a variable name or a URI-formatted string. + order: 45