2022-10-19 13:31:20 +01:00
|
|
|
/*
|
2024-09-09 14:57:16 +01:00
|
|
|
Copyright 2024 New Vector Ltd.
|
2022-10-19 13:31:20 +01:00
|
|
|
Copyright 2022 The Matrix.org Foundation C.I.C.
|
|
|
|
|
|
2024-09-09 14:57:16 +01:00
|
|
|
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
|
|
|
|
Please see LICENSE files in the repository root for full details.
|
2022-10-19 13:31:20 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import React from "react";
|
2023-04-06 04:06:12 -04:00
|
|
|
import {
|
2023-10-03 13:15:41 +01:00
|
|
|
IGetLoginTokenCapability,
|
2023-04-06 04:06:12 -04:00
|
|
|
IServerVersions,
|
2023-10-03 13:15:41 +01:00
|
|
|
GET_LOGIN_TOKEN_CAPABILITY,
|
2023-04-11 10:46:11 +01:00
|
|
|
Capabilities,
|
2023-09-28 10:37:44 +01:00
|
|
|
IClientWellKnown,
|
2024-06-06 09:57:28 +01:00
|
|
|
OidcClientConfig,
|
|
|
|
|
MatrixClient,
|
|
|
|
|
DEVICE_CODE_SCOPE,
|
2023-04-06 04:06:12 -04:00
|
|
|
} from "matrix-js-sdk/src/matrix";
|
2024-10-04 13:42:15 +01:00
|
|
|
import QrCodeIcon from "@vector-im/compound-design-tokens/assets/web/icons/qr-code";
|
2022-10-19 13:31:20 +01:00
|
|
|
|
|
|
|
|
import { _t } from "../../../../languageHandler";
|
|
|
|
|
import AccessibleButton from "../../elements/AccessibleButton";
|
|
|
|
|
import SettingsSubsection from "../shared/SettingsSubsection";
|
2024-06-06 09:57:28 +01:00
|
|
|
import SettingsStore from "../../../../settings/SettingsStore";
|
|
|
|
|
import { Features } from "../../../../settings/Settings";
|
|
|
|
|
import { useMatrixClientContext } from "../../../../contexts/MatrixClientContext";
|
2022-10-19 13:31:20 +01:00
|
|
|
|
|
|
|
|
interface IProps {
|
|
|
|
|
onShowQr: () => void;
|
2023-02-16 09:38:44 +00:00
|
|
|
versions?: IServerVersions;
|
2023-04-11 10:46:11 +01:00
|
|
|
capabilities?: Capabilities;
|
2023-09-28 10:37:44 +01:00
|
|
|
wellKnown?: IClientWellKnown;
|
2024-06-06 09:57:28 +01:00
|
|
|
oidcClientConfig?: OidcClientConfig;
|
|
|
|
|
isCrossSigningReady?: boolean;
|
2022-10-19 13:31:20 +01:00
|
|
|
}
|
|
|
|
|
|
2024-04-30 18:18:55 +01:00
|
|
|
function shouldShowQrLegacy(
|
|
|
|
|
versions?: IServerVersions,
|
|
|
|
|
wellKnown?: IClientWellKnown,
|
|
|
|
|
capabilities?: Capabilities,
|
|
|
|
|
): boolean {
|
|
|
|
|
// Needs server support for (get_login_token or OIDC Device Authorization Grant) and MSC3886:
|
|
|
|
|
// in r0 of MSC3882 it is exposed as a feature flag, but in stable and unstable r1 it is a capability
|
|
|
|
|
const loginTokenCapability = GET_LOGIN_TOKEN_CAPABILITY.findIn<IGetLoginTokenCapability>(capabilities);
|
|
|
|
|
const getLoginTokenSupported =
|
|
|
|
|
!!versions?.unstable_features?.["org.matrix.msc3882"] || !!loginTokenCapability?.enabled;
|
|
|
|
|
const msc3886Supported =
|
|
|
|
|
!!versions?.unstable_features?.["org.matrix.msc3886"] || !!wellKnown?.["io.element.rendezvous"]?.server;
|
|
|
|
|
return getLoginTokenSupported && msc3886Supported;
|
2022-10-19 13:31:20 +01:00
|
|
|
}
|
2024-04-30 18:18:55 +01:00
|
|
|
|
2024-06-06 09:57:28 +01:00
|
|
|
export function shouldShowQr(
|
|
|
|
|
cli: MatrixClient,
|
|
|
|
|
isCrossSigningReady: boolean,
|
|
|
|
|
oidcClientConfig?: OidcClientConfig,
|
|
|
|
|
versions?: IServerVersions,
|
|
|
|
|
wellKnown?: IClientWellKnown,
|
|
|
|
|
): boolean {
|
|
|
|
|
const msc4108Supported =
|
|
|
|
|
!!versions?.unstable_features?.["org.matrix.msc4108"] || !!wellKnown?.["io.element.rendezvous"]?.server;
|
|
|
|
|
|
|
|
|
|
const deviceAuthorizationGrantSupported =
|
|
|
|
|
oidcClientConfig?.metadata?.grant_types_supported.includes(DEVICE_CODE_SCOPE);
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
deviceAuthorizationGrantSupported &&
|
|
|
|
|
msc4108Supported &&
|
|
|
|
|
SettingsStore.getValue(Features.OidcNativeFlow) &&
|
|
|
|
|
!!cli.getCrypto()?.exportSecretsBundle &&
|
|
|
|
|
isCrossSigningReady
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const LoginWithQRSection: React.FC<IProps> = ({
|
|
|
|
|
onShowQr,
|
|
|
|
|
versions,
|
|
|
|
|
capabilities,
|
|
|
|
|
wellKnown,
|
|
|
|
|
oidcClientConfig,
|
|
|
|
|
isCrossSigningReady,
|
|
|
|
|
}) => {
|
|
|
|
|
const cli = useMatrixClientContext();
|
|
|
|
|
const offerShowQr = oidcClientConfig
|
|
|
|
|
? shouldShowQr(cli, !!isCrossSigningReady, oidcClientConfig, versions, wellKnown)
|
|
|
|
|
: shouldShowQrLegacy(versions, wellKnown, capabilities);
|
2024-04-30 18:18:55 +01:00
|
|
|
|
|
|
|
|
// don't show anything if no method is available
|
|
|
|
|
if (!offerShowQr) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<SettingsSubsection heading={_t("settings|sessions|sign_in_with_qr")}>
|
|
|
|
|
<div className="mx_LoginWithQRSection">
|
|
|
|
|
<p className="mx_SettingsTab_subsectionText">{_t("settings|sessions|sign_in_with_qr_description")}</p>
|
|
|
|
|
<AccessibleButton onClick={onShowQr} kind="primary">
|
|
|
|
|
<QrCodeIcon height={20} width={20} />
|
|
|
|
|
{_t("settings|sessions|sign_in_with_qr_button")}
|
|
|
|
|
</AccessibleButton>
|
|
|
|
|
</div>
|
|
|
|
|
</SettingsSubsection>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default LoginWithQRSection;
|