const logger = new Logger('steffo:meteor-accounts-saml', { methods: { updated: { type: 'info' } } }); RocketChat.settings.addGroup('SAML'); Meteor.methods({ addSamlService(name) { RocketChat.settings.add(`SAML_Custom_${ name }`, false, { type: 'boolean', group: 'SAML', section: name, i18nLabel: 'Accounts_OAuth_Custom_Enable' }); RocketChat.settings.add(`SAML_Custom_${ name }_provider`, 'provider-name', { type: 'string', group: 'SAML', section: name, i18nLabel: 'SAML_Custom_Provider' }); RocketChat.settings.add(`SAML_Custom_${ name }_entry_point`, 'https://example.com/simplesaml/saml2/idp/SSOService.php', { type: 'string', group: 'SAML', section: name, i18nLabel: 'SAML_Custom_Entry_point' }); RocketChat.settings.add(`SAML_Custom_${ name }_idp_slo_redirect_url`, 'https://example.com/simplesaml/saml2/idp/SingleLogoutService.php', { type: 'string', group: 'SAML', section: name, i18nLabel: 'SAML_Custom_IDP_SLO_Redirect_URL' }); RocketChat.settings.add(`SAML_Custom_${ name }_issuer`, 'https://your-rocket-chat/_saml/metadata/provider-name', { type: 'string', group: 'SAML', section: name, i18nLabel: 'SAML_Custom_Issuer' }); RocketChat.settings.add(`SAML_Custom_${ name }_cert`, '', { type: 'string', group: 'SAML', section: name, i18nLabel: 'SAML_Custom_Cert', multiline: true }); RocketChat.settings.add(`SAML_Custom_${ name }_public_cert`, '', { type: 'string', group: 'SAML', section: name, multiline: true, i18nLabel: 'SAML_Custom_Public_Cert' }); RocketChat.settings.add(`SAML_Custom_${ name }_private_key`, '', { type: 'string', group: 'SAML', section: name, multiline: true, i18nLabel: 'SAML_Custom_Private_Key' }); RocketChat.settings.add(`SAML_Custom_${ name }_button_label_text`, '', { type: 'string', group: 'SAML', section: name, i18nLabel: 'Accounts_OAuth_Custom_Button_Label_Text' }); RocketChat.settings.add(`SAML_Custom_${ name }_button_label_color`, '#FFFFFF', { type: 'string', group: 'SAML', section: name, i18nLabel: 'Accounts_OAuth_Custom_Button_Label_Color' }); RocketChat.settings.add(`SAML_Custom_${ name }_button_color`, '#13679A', { type: 'string', group: 'SAML', section: name, i18nLabel: 'Accounts_OAuth_Custom_Button_Color' }); RocketChat.settings.add(`SAML_Custom_${ name }_generate_username`, false, { type: 'boolean', group: 'SAML', section: name, i18nLabel: 'SAML_Custom_Generate_Username' }); } }); const getSamlConfigs = function(service) { return { buttonLabelText: RocketChat.settings.get(`${ service.key }_button_label_text`), buttonLabelColor: RocketChat.settings.get(`${ service.key }_button_label_color`), buttonColor: RocketChat.settings.get(`${ service.key }_button_color`), clientConfig: { provider: RocketChat.settings.get(`${ service.key }_provider`) }, entryPoint: RocketChat.settings.get(`${ service.key }_entry_point`), idpSLORedirectURL: RocketChat.settings.get(`${ service.key }_idp_slo_redirect_url`), generateUsername: RocketChat.settings.get(`${ service.key }_generate_username`), issuer: RocketChat.settings.get(`${ service.key }_issuer`), secret: { privateKey: RocketChat.settings.get(`${ service.key }_private_key`), publicCert: RocketChat.settings.get(`${ service.key }_public_cert`), cert: RocketChat.settings.get(`${ service.key }_cert`) } }; }; const debounce = (fn, delay) => { let timer = null; return () => { if (timer != null) { Meteor.clearTimeout(timer); } return timer = Meteor.setTimeout(fn, delay); }; }; const serviceName = 'saml'; const configureSamlService = function(samlConfigs) { let privateCert = false; let privateKey = false; if (samlConfigs.secret.privateKey && samlConfigs.secret.publicCert) { privateKey = samlConfigs.secret.privateKey; privateCert = samlConfigs.secret.publicCert; } else if (samlConfigs.secret.privateKey || samlConfigs.secret.publicCert) { logger.error('You must specify both cert and key files.'); } // TODO: the function configureSamlService is called many times and Accounts.saml.settings.generateUsername keeps just the last value Accounts.saml.settings.generateUsername = samlConfigs.generateUsername; return { provider: samlConfigs.clientConfig.provider, entryPoint: samlConfigs.entryPoint, idpSLORedirectURL: samlConfigs.idpSLORedirectURL, issuer: samlConfigs.issuer, cert: samlConfigs.secret.cert, privateCert, privateKey }; }; const updateServices = debounce(() => { const services = RocketChat.settings.get(/^(SAML_Custom_)[a-z]+$/i); Accounts.saml.settings.providers = services.map((service) => { if (service.value === true) { const samlConfigs = getSamlConfigs(service); logger.updated(service.key); ServiceConfiguration.configurations.upsert({ service: serviceName.toLowerCase() }, { $set: samlConfigs }); return configureSamlService(samlConfigs); } else { ServiceConfiguration.configurations.remove({ service: serviceName.toLowerCase() }); } }).filter(e => e); }, 2000); RocketChat.settings.get(/^SAML_.+/, updateServices); Meteor.startup(() => { return Meteor.call('addSamlService', 'Default'); }); export { updateServices, configureSamlService, getSamlConfigs, debounce, logger };