From bcfe1fcac521378ecfaabd1273259eaca83f5f3b Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 3 Mar 2020 23:23:53 -0700 Subject: [PATCH 1/6] Wire up 'create account' to the SSO button when SSO is used For https://github.com/vector-im/riot-web/issues/12362 --- src/components/structures/auth/Login.js | 27 ++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js index b918334d79..873c9e0c35 100644 --- a/src/components/structures/auth/Login.js +++ b/src/components/structures/auth/Login.js @@ -151,6 +151,18 @@ export default createReactClass({ return this.state.busy || this.props.busy; }, + _isSsoStep: function() { + return this._getCurrentFlowStep() === 'm.login.sso' || this._getCurrentFlowStep() === 'm.login.cas'; + }, + + _getSsoUrl: function(kind) { + if (kind === 'm.login.cas') { + return this._loginLogic.getSsoLoginUrl("cas") + } else { + return this._loginLogic.getSsoLoginUrl("sso"); + } + }, + onPasswordLogin: async function(username, phoneCountry, phoneNumber, password) { if (!this.state.serverIsAlive) { this.setState({busy: true}); @@ -339,6 +351,19 @@ export default createReactClass({ this.props.onRegisterClick(); }, + onTryRegisterClick: function(ev) { + if (this._isSsoStep()) { + // If we're showing SSO it means that registration is also probably disabled, + // so intercept the click and instead pretend the user clicked 'Sign in with SSO'. + ev.preventDefault(); + ev.stopPropagation(); + window.location = this._getSsoUrl(this._getCurrentFlowStep()); + } else { + // Don't intercept - just go through to the register page + this.onRegisterClick(ev); + } + }, + async onServerDetailsNextPhaseClick() { this.setState({ phase: PHASE_LOGIN, @@ -652,7 +677,7 @@ export default createReactClass({ { serverDeadSection } { this.renderServerComponent() } { this.renderLoginComponentForStep() } - + { _t('Create account') } From e265c92b6e87a434a0633e7ca62624fd0faa5fb2 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 3 Mar 2020 23:19:36 -0700 Subject: [PATCH 2/6] Redirect registration requests to Login when the server supports SSO For https://github.com/vector-im/riot-web/issues/12362 --- .../structures/auth/Registration.js | 43 ++++++++++++++----- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/src/components/structures/auth/Registration.js b/src/components/structures/auth/Registration.js index 8593a4b1e2..7c6a3ea56f 100644 --- a/src/components/structures/auth/Registration.js +++ b/src/components/structures/auth/Registration.js @@ -31,6 +31,8 @@ import classNames from "classnames"; import * as Lifecycle from '../../../Lifecycle'; import {MatrixClientPeg} from "../../../MatrixClientPeg"; import AuthPage from "../../views/auth/AuthPage"; +import Login from "../../../Login"; +import dis from "../../../dispatcher"; // Phases // Show controls to configure server details @@ -232,6 +234,13 @@ export default createReactClass({ serverRequiresIdServer, busy: false, }); + const showGenericError = (e) => { + this.setState({ + errorText: _t("Unable to query for supported registration methods."), + // add empty flows array to get rid of spinner + flows: [], + }); + }; try { await this._makeRegisterRequest({}); // This should never succeed since we specified an empty @@ -243,18 +252,32 @@ export default createReactClass({ flows: e.data.flows, }); } else if (e.httpStatus === 403 && e.errcode === "M_UNKNOWN") { - this.setState({ - errorText: _t("Registration has been disabled on this homeserver."), - // add empty flows array to get rid of spinner - flows: [], - }); + // At this point registration is pretty much disabled, but before we do that let's + // quickly check to see if the server supports SSO instead. If it does, we'll send + // the user off to the login page to figure their account out. + try { + const loginLogic = new Login(hsUrl, isUrl, null, { + defaultDeviceDisplayName: "riot login check", // We shouldn't ever be used + }); + const flows = await loginLogic.getFlows(); + const hasSsoFlow = flows.find(f => f.type === 'm.login.sso' || f.type === 'm.login.cas'); + if (hasSsoFlow) { + // Redirect to login page - server probably expects SSO only + dis.dispatch({action: 'start_login'}); + } else { + this.setState({ + errorText: _t("Registration has been disabled on this homeserver."), + // add empty flows array to get rid of spinner + flows: [], + }); + } + } catch (e) { + console.error("Failed to get login flows to check for SSO support", e); + showGenericError(e); + } } else { console.log("Unable to query for supported registration methods.", e); - this.setState({ - errorText: _t("Unable to query for supported registration methods."), - // add empty flows array to get rid of spinner - flows: [], - }); + showGenericError(e); } } }, From e83a4ddbe5a0b23a5f0dbd10ff8ae72d2d18059c Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 3 Mar 2020 23:23:12 -0700 Subject: [PATCH 3/6] i18n --- src/i18n/strings/en_EN.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 4ec9c1e281..2b1d44bbcd 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2007,8 +2007,8 @@ "Failed to fetch avatar URL": "Failed to fetch avatar URL", "Set a display name:": "Set a display name:", "Upload an avatar:": "Upload an avatar:", - "Registration has been disabled on this homeserver.": "Registration has been disabled on this homeserver.", "Unable to query for supported registration methods.": "Unable to query for supported registration methods.", + "Registration has been disabled on this homeserver.": "Registration has been disabled on this homeserver.", "This server does not support authentication with a phone number.": "This server does not support authentication with a phone number.", "Your new account (%(newAccountId)s) is registered, but you're already logged into a different account (%(loggedInUserId)s).": "Your new account (%(newAccountId)s) is registered, but you're already logged into a different account (%(loggedInUserId)s).", "Continue with previous account": "Continue with previous account", From 3cff6d72394efe8c942841c49c0473459480f6bb Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 3 Mar 2020 23:26:20 -0700 Subject: [PATCH 4/6] Appease the linter --- src/components/structures/auth/Login.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js index 873c9e0c35..cf80c99535 100644 --- a/src/components/structures/auth/Login.js +++ b/src/components/structures/auth/Login.js @@ -157,7 +157,7 @@ export default createReactClass({ _getSsoUrl: function(kind) { if (kind === 'm.login.cas') { - return this._loginLogic.getSsoLoginUrl("cas") + return this._loginLogic.getSsoLoginUrl("cas"); } else { return this._loginLogic.getSsoLoginUrl("sso"); } From 3842bce74dc25f242b0cf710efd6d5d6d61ec3f9 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 4 Mar 2020 11:41:16 -0700 Subject: [PATCH 5/6] Fix SSO for new approach --- src/components/structures/auth/Login.js | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js index cf80c99535..6cce8f4444 100644 --- a/src/components/structures/auth/Login.js +++ b/src/components/structures/auth/Login.js @@ -28,6 +28,7 @@ import AutoDiscoveryUtils, {ValidatedServerConfig} from "../../../utils/AutoDisc import classNames from "classnames"; import AuthPage from "../../views/auth/AuthPage"; import SSOButton from "../../views/elements/SSOButton"; +import PlatformPeg from '../../../PlatformPeg'; // For validating phone numbers without country codes const PHONE_NUMBER_REGEX = /^[0-9()\-\s]*$/; @@ -155,14 +156,6 @@ export default createReactClass({ return this._getCurrentFlowStep() === 'm.login.sso' || this._getCurrentFlowStep() === 'm.login.cas'; }, - _getSsoUrl: function(kind) { - if (kind === 'm.login.cas') { - return this._loginLogic.getSsoLoginUrl("cas"); - } else { - return this._loginLogic.getSsoLoginUrl("sso"); - } - }, - onPasswordLogin: async function(username, phoneCountry, phoneNumber, password) { if (!this.state.serverIsAlive) { this.setState({busy: true}); @@ -357,7 +350,8 @@ export default createReactClass({ // so intercept the click and instead pretend the user clicked 'Sign in with SSO'. ev.preventDefault(); ev.stopPropagation(); - window.location = this._getSsoUrl(this._getCurrentFlowStep()); + const ssoKind = this._getCurrentFlowStep() === 'm.login.sso' ? 'sso' : 'cas'; + PlatformPeg.get().startSingleSignOn(this._loginLogic.createTemporaryClient(), ssoKind); } else { // Don't intercept - just go through to the register page this.onRegisterClick(ev); From 2204785026ceaf504ef29c4f0fe0f4c11979aa90 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 4 Mar 2020 12:26:08 -0700 Subject: [PATCH 6/6] Simplify SSO step checking --- src/components/structures/auth/Login.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js index 6cce8f4444..bfabc34a62 100644 --- a/src/components/structures/auth/Login.js +++ b/src/components/structures/auth/Login.js @@ -152,10 +152,6 @@ export default createReactClass({ return this.state.busy || this.props.busy; }, - _isSsoStep: function() { - return this._getCurrentFlowStep() === 'm.login.sso' || this._getCurrentFlowStep() === 'm.login.cas'; - }, - onPasswordLogin: async function(username, phoneCountry, phoneNumber, password) { if (!this.state.serverIsAlive) { this.setState({busy: true}); @@ -345,12 +341,13 @@ export default createReactClass({ }, onTryRegisterClick: function(ev) { - if (this._isSsoStep()) { + const step = this._getCurrentFlowStep(); + if (step === 'm.login.sso' || step === 'm.login.cas') { // If we're showing SSO it means that registration is also probably disabled, // so intercept the click and instead pretend the user clicked 'Sign in with SSO'. ev.preventDefault(); ev.stopPropagation(); - const ssoKind = this._getCurrentFlowStep() === 'm.login.sso' ? 'sso' : 'cas'; + const ssoKind = step === 'm.login.sso' ? 'sso' : 'cas'; PlatformPeg.get().startSingleSignOn(this._loginLogic.createTemporaryClient(), ssoKind); } else { // Don't intercept - just go through to the register page