{
);
} else if (this.state.view === Views.LOGGED_IN) {
diff --git a/src/components/structures/auth/E2eSetup.js b/src/components/structures/auth/E2eSetup.js
index 6df8158002..d97a972718 100644
--- a/src/components/structures/auth/E2eSetup.js
+++ b/src/components/structures/auth/E2eSetup.js
@@ -24,6 +24,7 @@ export default class E2eSetup extends React.Component {
static propTypes = {
onFinished: PropTypes.func.isRequired,
accountPassword: PropTypes.string,
+ tokenLogin: PropTypes.bool,
};
render() {
@@ -33,6 +34,7 @@ export default class E2eSetup extends React.Component {
diff --git a/src/components/views/auth/InteractiveAuthEntryComponents.js b/src/components/views/auth/InteractiveAuthEntryComponents.js
index 60e57afc98..7dc1976641 100644
--- a/src/components/views/auth/InteractiveAuthEntryComponents.js
+++ b/src/components/views/auth/InteractiveAuthEntryComponents.js
@@ -609,8 +609,12 @@ export class SSOAuthEntry extends React.Component {
this.props.authSessionId,
);
+ this._popupWindow = null;
+ window.addEventListener("message", this._onReceiveMessage);
+
this.state = {
phase: SSOAuthEntry.PHASE_PREAUTH,
+ attemptFailed: false,
};
}
@@ -618,12 +622,35 @@ export class SSOAuthEntry extends React.Component {
this.props.onPhaseChange(SSOAuthEntry.PHASE_PREAUTH);
}
+ componentWillUnmount() {
+ window.removeEventListener("message", this._onReceiveMessage);
+ if (this._popupWindow) {
+ this._popupWindow.close();
+ this._popupWindow = null;
+ }
+ }
+
+ attemptFailed = () => {
+ this.setState({
+ attemptFailed: true,
+ });
+ };
+
+ _onReceiveMessage = event => {
+ if (event.data === "authDone" && event.origin === this.props.matrixClient.getHomeserverUrl()) {
+ if (this._popupWindow) {
+ this._popupWindow.close();
+ this._popupWindow = null;
+ }
+ }
+ };
+
onStartAuthClick = () => {
// Note: We don't use PlatformPeg's startSsoAuth functions because we almost
// certainly will need to open the thing in a new tab to avoid losing application
// context.
- window.open(this._ssoUrl, '_blank');
+ this._popupWindow = window.open(this._ssoUrl, "_blank");
this.setState({phase: SSOAuthEntry.PHASE_POSTAUTH});
this.props.onPhaseChange(SSOAuthEntry.PHASE_POSTAUTH);
};
@@ -656,10 +683,28 @@ export class SSOAuthEntry extends React.Component {
);
}
- return
- {cancelButton}
- {continueButton}
-
;
+ let errorSection;
+ if (this.props.errorText) {
+ errorSection = (
+
+ { this.props.errorText }
+
+ );
+ } else if (this.state.attemptFailed) {
+ errorSection = (
+
+ { _t("Something went wrong in confirming your identity. Cancel and try again.") }
+
+ );
+ }
+
+ return
+ { errorSection }
+
+ {cancelButton}
+ {continueButton}
+
+ ;
}
}
@@ -710,8 +755,7 @@ export class FallbackAuthEntry extends React.Component {
this.props.loginType,
this.props.authSessionId,
);
- this._popupWindow = window.open(url);
- this._popupWindow.opener = null;
+ this._popupWindow = window.open(url, "_blank");
};
_onReceiveMessage = event => {
diff --git a/src/components/views/dialogs/security/CreateCrossSigningDialog.js b/src/components/views/dialogs/security/CreateCrossSigningDialog.js
index 226419e759..be546d2616 100644
--- a/src/components/views/dialogs/security/CreateCrossSigningDialog.js
+++ b/src/components/views/dialogs/security/CreateCrossSigningDialog.js
@@ -34,6 +34,7 @@ import InteractiveAuthDialog from '../InteractiveAuthDialog';
export default class CreateCrossSigningDialog extends React.PureComponent {
static propTypes = {
accountPassword: PropTypes.string,
+ tokenLogin: PropTypes.bool,
};
constructor(props) {
@@ -96,6 +97,9 @@ export default class CreateCrossSigningDialog extends React.PureComponent {
user: MatrixClientPeg.get().getUserId(),
password: this.state.accountPassword,
});
+ } else if (this.props.tokenLogin) {
+ // We are hoping the grace period is active
+ await makeRequest({});
} else {
const dialogAesthetics = {
[SSOAuthEntry.PHASE_PREAUTH]: {
@@ -144,6 +148,12 @@ export default class CreateCrossSigningDialog extends React.PureComponent {
});
this.props.onFinished(true);
} catch (e) {
+ if (this.props.tokenLogin) {
+ // ignore any failures, we are relying on grace period here
+ this.props.onFinished();
+ return;
+ }
+
this.setState({ error: e });
console.error("Error bootstrapping cross-signing", e);
}
diff --git a/src/components/views/elements/SSOButtons.tsx b/src/components/views/elements/SSOButtons.tsx
index 5c3098d807..3a03252ebd 100644
--- a/src/components/views/elements/SSOButtons.tsx
+++ b/src/components/views/elements/SSOButtons.tsx
@@ -22,13 +22,33 @@ import {MatrixClient} from "matrix-js-sdk/src/client";
import PlatformPeg from "../../../PlatformPeg";
import AccessibleButton from "./AccessibleButton";
import {_t} from "../../../languageHandler";
-import {IIdentityProvider, ISSOFlow} from "../../../Login";
+import {IdentityProviderBrand, IIdentityProvider, ISSOFlow} from "../../../Login";
+import AccessibleTooltipButton from "./AccessibleTooltipButton";
interface ISSOButtonProps extends Omit {
idp: IIdentityProvider;
mini?: boolean;
}
+const getIcon = (brand: IdentityProviderBrand | string) => {
+ switch (brand) {
+ case IdentityProviderBrand.Apple:
+ return require(`../../../../res/img/element-icons/brands/apple.svg`);
+ case IdentityProviderBrand.Facebook:
+ return require(`../../../../res/img/element-icons/brands/facebook.svg`);
+ case IdentityProviderBrand.Github:
+ return require(`../../../../res/img/element-icons/brands/github.svg`);
+ case IdentityProviderBrand.Gitlab:
+ return require(`../../../../res/img/element-icons/brands/gitlab.svg`);
+ case IdentityProviderBrand.Google:
+ return require(`../../../../res/img/element-icons/brands/google.svg`);
+ case IdentityProviderBrand.Twitter:
+ return require(`../../../../res/img/element-icons/brands/twitter.svg`);
+ default:
+ return null;
+ }
+}
+
const SSOButton: React.FC = ({
matrixClient,
loginType,
@@ -38,7 +58,6 @@ const SSOButton: React.FC = ({
mini,
...props
}) => {
- const kind = primary ? "primary" : "primary_outline";
const label = idp ? _t("Continue with %(provider)s", { provider: idp.name }) : _t("Sign in with single sign-on");
const onClick = () => {
@@ -46,30 +65,35 @@ const SSOButton: React.FC = ({
};
let icon;
- if (typeof idp?.icon === "string" && (idp.icon.startsWith("mxc://") || idp.icon.startsWith("https://"))) {
- icon = ;
+ let brandClass;
+ const brandIcon = idp ? getIcon(idp.brand) : null;
+ if (brandIcon) {
+ const brandName = idp.brand.split(".").pop();
+ brandClass = `mx_SSOButton_brand_${brandName}`;
+ icon = ;
+ } else if (typeof idp?.icon === "string" && idp.icon.startsWith("mxc://")) {
+ const src = matrixClient.mxcUrlToHttp(idp.icon, 24, 24, "crop", true);
+ icon = ;
}
const classes = classNames("mx_SSOButton", {
+ [brandClass]: brandClass,
mx_SSOButton_mini: mini,
+ mx_SSOButton_default: !idp,
+ mx_SSOButton_primary: primary,
});
if (mini) {
// TODO fallback icon
return (
-
+
{ icon }
-
+
);
}
return (
-
+
{ icon }
{ label }
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index 54ad41b814..235c72be92 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -2339,6 +2339,7 @@
"Please enter the code it contains:": "Please enter the code it contains:",
"Code": "Code",
"Submit": "Submit",
+ "Something went wrong in confirming your identity. Cancel and try again.": "Something went wrong in confirming your identity. Cancel and try again.",
"Start authentication": "Start authentication",
"Enter password": "Enter password",
"Nice, strong password!": "Nice, strong password!",