[NEW] OAuth groups to channels mapping (#18146)

Co-authored-by: pierre-lehnen-rc <55164754+pierre-lehnen-rc@users.noreply.github.com>
pull/19358/head
arminfelder 5 years ago committed by GitHub
parent 368a3624cd
commit ae6a37499e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 23
      app/custom-oauth/server/custom_oauth_server.js
  2. 33
      app/custom-oauth/server/oauth_helpers.js
  3. 4
      app/lib/server/methods/addOAuthService.js
  4. 8
      app/lib/server/startup/oAuthServicesUpdate.js
  5. 4
      packages/rocketchat-i18n/i18n/en.i18n.json

@ -7,7 +7,7 @@ import { ServiceConfiguration } from 'meteor/service-configuration';
import _ from 'underscore';
import { normalizers, fromTemplate, renameInvalidProperties } from './transform_helpers';
import { mapRolesFromSSO, updateRolesFromSSO } from './oauth_helpers';
import { mapRolesFromSSO, mapSSOGroupsToChannels, updateRolesFromSSO } from './oauth_helpers';
import { Logger } from '../../logger';
import { Users } from '../../models';
import { isURL } from '../../utils/lib/isURL';
@ -79,8 +79,21 @@ export class CustomOAuth {
this.avatarField = (options.avatarField || '').trim();
this.mergeUsers = options.mergeUsers;
this.mergeRoles = options.mergeRoles || false;
this.mapChannels = options.mapChannels || false;
this.rolesClaim = options.rolesClaim || 'roles';
this.groupsClaim = options.groupsClaim || 'groups';
this.accessTokenParam = options.accessTokenParam;
this.channelsAdmin = options.channelsAdmin || 'rocket.cat';
if (this.mapChannels) {
const channelsMap = (options.channelsMap || '{}').trim();
try {
this.channelsMap = JSON.parse(channelsMap);
} catch (err) {
logger.error(`Unexpected error : ${ err.message }`);
}
}
if (this.identityTokenSentVia == null || this.identityTokenSentVia === 'default') {
this.identityTokenSentVia = this.tokenSentVia;
@ -330,6 +343,10 @@ export class CustomOAuth {
updateRolesFromSSO(user, serviceData, this.rolesClaim);
}
if (this.mapChannels) {
mapSSOGroupsToChannels(user, serviceData, this.groupsClaim, this.channelsMap, this.channelsAdmin);
}
// User already created or merged and has identical name as before
if (user.services && user.services[serviceName] && user.services[serviceName].id === serviceData.id && user.name === serviceData.name) {
return;
@ -372,6 +389,10 @@ export class CustomOAuth {
user.roles = mapRolesFromSSO(user.services[this.name], this.rolesClaim);
}
if (this.mapChannels) {
mapSSOGroupsToChannels(user, user.services[this.name], this.groupsClaim, this.channelsMap, this.channelsAdmin);
}
return true;
});
}

@ -1,6 +1,9 @@
import { addUserRoles, removeUserFromRoles } from '../../authorization';
import { Roles } from '../../models';
import { Roles, Rooms } from '../../models';
import { addUserToRoom, createRoom } from '../../lib/server/functions';
import { Logger } from '../../logger';
export const logger = new Logger('OAuth', {});
// Returns list of roles from SSO identity
export function mapRolesFromSSO(identity, roleClaimName) {
@ -40,3 +43,31 @@ export function updateRolesFromSSO(user, identity, roleClaimName) {
});
}
}
export function mapSSOGroupsToChannels(user, identity, groupClaimName, channelsMap, channelsAdmin) {
if (user && identity && groupClaimName) {
const groupsFromSSO = identity[groupClaimName] || [];
for (const ssoGroup in channelsMap) {
if (typeof ssoGroup === 'string') {
let channels = channelsMap[ssoGroup];
if (!Array.isArray(channels)) {
channels = [channels];
}
for (const channel of channels) {
let room = Rooms.findOneByNonValidatedName(channel);
if (!room) {
room = createRoom('c', channel, channelsAdmin, [], false);
if (!room || !room.rid) {
logger.error(`could not create channel ${ channel }`);
return;
}
}
if (Array.isArray(groupsFromSSO) && groupsFromSSO.includes(ssoGroup)) {
addUserToRoom(room._id, user);
}
}
}
}
}
}

@ -41,6 +41,10 @@ Meteor.methods({
settings.add(`Accounts_OAuth_Custom-${ name }-name_field` , '' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_Name_Field', persistent: true });
settings.add(`Accounts_OAuth_Custom-${ name }-avatar_field` , '' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_Avatar_Field', persistent: true });
settings.add(`Accounts_OAuth_Custom-${ name }-roles_claim` , 'roles' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_Roles_Claim', persistent: true });
settings.add(`Accounts_OAuth_Custom-${ name }-groups_claim` , 'groups' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_Groups_Claim', persistent: true });
settings.add(`Accounts_OAuth_Custom-${ name }-channels_admin` , 'rocket.cat' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_Channel_Admin', persistent: true });
settings.add(`Accounts_OAuth_Custom-${ name }-groups_channel_map` , '{\n\t"rocket-admin": "admin",\n\t"tech-support": "support"\n}' , { type: 'code' , multiline: true, code: 'application/json', group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_Channel_Map', persistent: true });
settings.add(`Accounts_OAuth_Custom-${ name }-map_channels` , false , { type: 'boolean', group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_Map_Channels', persistent: true });
settings.add(`Accounts_OAuth_Custom-${ name }-merge_roles` , false , { type: 'boolean', group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_Merge_Roles', persistent: true });
settings.add(`Accounts_OAuth_Custom-${ name }-merge_users` , false , { type: 'boolean', group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_Merge_Users', persistent: true });
settings.add(`Accounts_OAuth_Custom-${ name }-show_button` , true , { type: 'boolean', group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_Show_Button_On_Login_Page', persistent: true });

@ -51,7 +51,11 @@ function _OAuthServicesUpdate() {
data.nameField = settings.get(`${ service.key }-name_field`);
data.avatarField = settings.get(`${ service.key }-avatar_field`);
data.rolesClaim = settings.get(`${ service.key }-roles_claim`);
data.groupsClaim = settings.get(`${ service.key }-groups_claim`);
data.channelsMap = settings.get(`${ service.key }-groups_channel_map`);
data.channelsAdmin = settings.get(`${ service.key }-channels_admin`);
data.mergeUsers = settings.get(`${ service.key }-merge_users`);
data.mapChannels = settings.get(`${ service.key }-map_channels`);
data.mergeRoles = settings.get(`${ service.key }-merge_roles`);
data.showButton = settings.get(`${ service.key }-show_button`);
new CustomOAuth(serviceName.toLowerCase(), {
@ -68,6 +72,10 @@ function _OAuthServicesUpdate() {
nameField: data.nameField,
avatarField: data.avatarField,
rolesClaim: data.rolesClaim,
groupsClaim: data.groupsClaim,
mapChannels: data.mapChannels,
channelsMap: data.channelsMap,
channelsAdmin: data.channelsAdmin,
mergeUsers: data.mergeUsers,
mergeRoles: data.mergeRoles,
accessTokenParam: data.accessTokenParam,

@ -127,7 +127,11 @@
"Accounts_OAuth_Custom_Email_Field": "Email field",
"Accounts_OAuth_Custom_Name_Field": "Name field",
"Accounts_OAuth_Custom_Roles_Claim": "Roles/Groups field name",
"Accounts_OAuth_Custom_Groups_Claim": "Roles/Groups field for channel mapping",
"Accounts_OAuth_Custom_Channel_Admin": "User Data Group Map",
"Accounts_OAuth_Custom_Channel_Map": "OAuth Group Channel Map",
"Accounts_OAuth_Custom_Merge_Roles": "Merge Roles from SSO",
"Accounts_OAuth_Custom_Map_Channels": "Map Roles/Groups to channels",
"Accounts_OAuth_Drupal": "Drupal Login Enabled",
"Accounts_OAuth_Drupal_callback_url": "Drupal oAuth2 Redirect URI",
"Accounts_OAuth_Drupal_id": "Drupal oAuth2 Client ID",

Loading…
Cancel
Save