From e351a77a6b3bb95156af2d64e9089d848212cd7a Mon Sep 17 00:00:00 2001 From: Filipe Brito Date: Mon, 12 Aug 2019 15:37:42 -0300 Subject: [PATCH] [NEW] CAS authentication (#1116) --- app/constants/settings.js | 6 ++++++ app/lib/rocketchat.js | 4 ++++ app/views/AuthenticationWebView.js | 14 ++++++++++---- app/views/LoginSignupView.js | 20 ++++++++++++++++++-- 4 files changed, 38 insertions(+), 6 deletions(-) diff --git a/app/constants/settings.js b/app/constants/settings.js index d602f290..8fcbb1b5 100644 --- a/app/constants/settings.js +++ b/app/constants/settings.js @@ -82,5 +82,11 @@ export default { }, AutoTranslate_Enabled: { type: 'valueAsBoolean' + }, + CAS_enabled: { + type: 'valueAsBoolean' + }, + CAS_login_url: { + type: 'valueAsString' } }; diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index d3efaa4b..3955f966 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -812,6 +812,10 @@ const RocketChat = { return 'saml'; } + if (service === 'cas') { + return 'cas'; + } + // TODO: remove this after other oauth providers are implemented. e.g. Drupal, github_enterprise const availableOAuth = ['facebook', 'github', 'gitlab', 'google', 'linkedin', 'meteor-developer', 'twitter']; return availableOAuth.includes(name) ? 'oauth' : 'not_supported'; diff --git a/app/views/AuthenticationWebView.js b/app/views/AuthenticationWebView.js index 2895f3ce..a1c2757d 100644 --- a/app/views/AuthenticationWebView.js +++ b/app/views/AuthenticationWebView.js @@ -29,7 +29,7 @@ class AuthenticationWebView extends React.PureComponent { const authType = navigation.getParam('authType', 'oauth'); return { headerLeft: , - title: authType === 'saml' ? 'SSO' : 'OAuth' + title: authType === 'saml' || authType === 'cas' ? 'SSO' : 'OAuth' }; } @@ -72,15 +72,21 @@ class AuthenticationWebView extends React.PureComponent { onNavigationStateChange = (webViewState) => { const url = decodeURIComponent(webViewState.url); - if (this.authType === 'saml') { + if (this.authType === 'saml' || this.authType === 'cas') { const { navigation } = this.props; const ssoToken = navigation.getParam('ssoToken'); if (url.includes('ticket') || url.includes('validate')) { - const payload = `{ "saml": true, "credentialToken": "${ ssoToken }" }`; + let payload; + const credentialToken = { credentialToken: ssoToken }; + if (this.authType === 'saml') { + payload = { ...credentialToken, saml: true }; + } else { + payload = { cas: credentialToken }; + } // We need to set a timeout when the login is done with SSO in order to make it work on our side. // It is actually due to the SSO server processing the response. setTimeout(() => { - this.login(JSON.parse(payload)); + this.login(payload); }, 3000); } } diff --git a/app/views/LoginSignupView.js b/app/views/LoginSignupView.js index 36e530e5..3e795bcc 100644 --- a/app/views/LoginSignupView.js +++ b/app/views/LoginSignupView.js @@ -102,7 +102,9 @@ class LoginSignupView extends React.Component { server: PropTypes.string, services: PropTypes.object, Site_Name: PropTypes.string, - Gitlab_URL: PropTypes.string + Gitlab_URL: PropTypes.string, + CAS_enabled: PropTypes.bool, + CAS_login_url: PropTypes.string } constructor(props) { @@ -242,6 +244,13 @@ class LoginSignupView extends React.Component { this.openOAuth({ url, ssoToken, authType: 'saml' }); } + onPressCas = () => { + const { server, CAS_login_url } = this.props; + const ssoToken = random(17); + const url = `${ CAS_login_url }/?service=${ server }/_cas/${ ssoToken }`; + this.openOAuth({ url, ssoToken, authType: 'cas' }); + } + getOAuthState = () => { const credentialToken = random(43); return Base64.encodeURI(JSON.stringify({ loginStyle: 'popup', credentialToken, isCordova: true })); @@ -341,12 +350,17 @@ class LoginSignupView extends React.Component { onPress = () => this.onPressSaml(service); break; } + case 'cas': { + onPress = () => this.onPressCas(); + break; + } default: break; } name = name.charAt(0).toUpperCase() + name.slice(1); + const { CAS_enabled } = this.props; let buttonText; - if (service.service === 'saml') { + if (service.service === 'saml' || (service.service === 'cas' && CAS_enabled)) { buttonText = {name}; } else { buttonText = ( @@ -418,6 +432,8 @@ const mapStateToProps = state => ({ server: state.server.server, Site_Name: state.settings.Site_Name, Gitlab_URL: state.settings.API_Gitlab_URL, + CAS_enabled: state.settings.CAS_enabled, + CAS_login_url: state.settings.CAS_login_url, services: state.login.services });