The communications platform that puts data protection first.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
Rocket.Chat/packages/meteor-accounts-saml/client/saml_client.js

123 lines
4.4 KiB

import { Meteor } from 'meteor/meteor';
import { Accounts } from 'meteor/accounts-base';
import { Random } from 'meteor/random';
import { ServiceConfiguration } from 'meteor/service-configuration';
if (!Accounts.saml) {
Accounts.saml = {};
}
// Override the standard logout behaviour.
//
// If we find a samlProvider, and we are using single
// logout we will initiate logout from rocketchat via saml.
// If not using single logout, we just do the standard logout.
// This can be overridden by a configured logout behaviour.
//
// TODO: This may need some work as it is not clear if we are really
// logging out of the idp when doing the standard logout.
const MeteorLogout = Meteor.logout;
const logoutBehaviour = {
TERMINATE_SAML: 'SAML',
ONLY_RC: 'Local',
};
Meteor.logout = function(...args) {
const samlService = ServiceConfiguration.configurations.findOne({ service: 'saml' });
if (samlService) {
const provider = samlService.clientConfig && samlService.clientConfig.provider;
if (provider) {
if (samlService.logoutBehaviour == null || samlService.logoutBehaviour === logoutBehaviour.TERMINATE_SAML) {
if (samlService.idpSLORedirectURL) {
console.info('SAML session terminated via SLO');
return Meteor.logoutWithSaml({ provider });
}
}
if (samlService.logoutBehaviour === logoutBehaviour.ONLY_RC) {
console.info('SAML session not terminated, only the Rocket.Chat session is going to be killed');
}
}
}
return MeteorLogout.apply(Meteor, args);
};
const openCenteredPopup = function(url, width, height) {
const screenX = typeof window.screenX !== 'undefined' ? window.screenX : window.screenLeft;
const screenY = typeof window.screenY !== 'undefined' ? window.screenY : window.screenTop;
const outerWidth = typeof window.outerWidth !== 'undefined' ? window.outerWidth : document.body.clientWidth;
const outerHeight = typeof window.outerHeight !== 'undefined' ? window.outerHeight : (document.body.clientHeight - 22);
// XXX what is the 22?
// Use `outerWidth - width` and `outerHeight - height` for help in
// positioning the popup centered relative to the current window
const left = screenX + (outerWidth - width) / 2;
const top = screenY + (outerHeight - height) / 2;
const features = (`width=${ width },height=${ height
},left=${ left },top=${ top },scrollbars=yes`);
const newwindow = window.open(url, 'Login', features);
if (newwindow.focus) {
newwindow.focus();
}
return newwindow;
};
Accounts.saml.initiateLogin = function(options, callback, dimensions) {
// default dimensions that worked well for facebook and google
const popup = openCenteredPopup(
Meteor.absoluteUrl(`_saml/authorize/${ options.provider }/${ options.credentialToken }`), (dimensions && dimensions.width) || 650, (dimensions && dimensions.height) || 500);
const checkPopupOpen = setInterval(function() {
let popupClosed;
try {
// Fix for #328 - added a second test criteria (popup.closed === undefined)
// to humour this Android quirk:
// http://code.google.com/p/android/issues/detail?id=21061
popupClosed = popup.closed || popup.closed === undefined;
} catch (e) {
// For some unknown reason, IE9 (and others?) sometimes (when
// the popup closes too quickly?) throws 'SCRIPT16386: No such
// interface supported' when trying to read 'popup.closed'. Try
// again in 100ms.
return;
}
if (popupClosed) {
clearInterval(checkPopupOpen);
callback(options.credentialToken);
}
}, 100);
};
Meteor.loginWithSaml = function(options, callback) {
options = options || {};
const credentialToken = `id-${ Random.id() }`;
options.credentialToken = credentialToken;
Accounts.saml.initiateLogin(options, function(/* error, result*/) {
Accounts.callLoginMethod({
methodArguments: [{
saml: true,
credentialToken,
}],
userCallback: callback,
});
});
};
Meteor.logoutWithSaml = function(options/* , callback*/) {
// Accounts.saml.idpInitiatedSLO(options, callback);
Meteor.call('samlLogout', options.provider, function(err, result) {
if (err || !result) {
MeteorLogout.apply(Meteor);
return;
}
// A nasty bounce: 'result' has the SAML LogoutRequest but we need a proper 302 to redirected from the server.
// window.location.replace(Meteor.absoluteUrl('_saml/sloRedirect/' + options.provider + '/?redirect='+result));
window.location.replace(Meteor.absoluteUrl(`_saml/sloRedirect/${ options.provider }/?redirect=${ encodeURIComponent(result) }`));
});
};