Implementation of MSC3824 to make the client OIDC-aware (#8681)

This commit is contained in:
Hugh Nimmo-Smith 2023-01-27 11:06:10 +00:00 committed by GitHub
parent 32bd350b7e
commit d698193196
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 240 additions and 29 deletions

View file

@ -19,7 +19,13 @@ import { chunk } from "lodash";
import classNames from "classnames";
import { MatrixClient } from "matrix-js-sdk/src/client";
import { Signup } from "@matrix-org/analytics-events/types/typescript/Signup";
import { IdentityProviderBrand, IIdentityProvider, ISSOFlow } from "matrix-js-sdk/src/@types/auth";
import {
IdentityProviderBrand,
IIdentityProvider,
ISSOFlow,
DELEGATED_OIDC_COMPATIBILITY,
SSOAction,
} from "matrix-js-sdk/src/@types/auth";
import PlatformPeg from "../../../PlatformPeg";
import AccessibleButton from "./AccessibleButton";
@ -28,9 +34,10 @@ import AccessibleTooltipButton from "./AccessibleTooltipButton";
import { mediaFromMxc } from "../../../customisations/Media";
import { PosthogAnalytics } from "../../../PosthogAnalytics";
interface ISSOButtonProps extends Omit<IProps, "flow"> {
interface ISSOButtonProps extends IProps {
idp?: IIdentityProvider;
mini?: boolean;
action?: SSOAction;
}
const getIcon = (brand: IdentityProviderBrand | string): string | null => {
@ -79,20 +86,29 @@ const SSOButton: React.FC<ISSOButtonProps> = ({
idp,
primary,
mini,
action,
flow,
...props
}) => {
const label = idp ? _t("Continue with %(provider)s", { provider: idp.name }) : _t("Sign in with single sign-on");
let label: string;
if (idp) {
label = _t("Continue with %(provider)s", { provider: idp.name });
} else if (DELEGATED_OIDC_COMPATIBILITY.findIn<boolean>(flow)) {
label = _t("Continue");
} else {
label = _t("Sign in with single sign-on");
}
const onClick = (): void => {
const authenticationType = getAuthenticationType(idp?.brand ?? "");
PosthogAnalytics.instance.setAuthenticationType(authenticationType);
PlatformPeg.get().startSingleSignOn(matrixClient, loginType, fragmentAfterLogin, idp?.id);
PlatformPeg.get()?.startSingleSignOn(matrixClient, loginType, fragmentAfterLogin, idp?.id, action);
};
let icon;
let brandClass;
const brandIcon = idp ? getIcon(idp.brand) : null;
if (brandIcon) {
let icon: JSX.Element | undefined;
let brandClass: string | undefined;
const brandIcon = idp?.brand ? getIcon(idp.brand) : null;
if (idp?.brand && brandIcon) {
const brandName = idp.brand.split(".").pop();
brandClass = `mx_SSOButton_brand_${brandName}`;
icon = <img src={brandIcon} height="24" width="24" alt={brandName} />;
@ -101,12 +117,16 @@ const SSOButton: React.FC<ISSOButtonProps> = ({
icon = <img src={src} height="24" width="24" alt={idp.name} />;
}
const classes = classNames("mx_SSOButton", {
[brandClass]: brandClass,
mx_SSOButton_mini: mini,
mx_SSOButton_default: !idp,
mx_SSOButton_primary: primary,
});
const brandPart = brandClass ? { [brandClass]: brandClass } : undefined;
const classes = classNames(
"mx_SSOButton",
{
mx_SSOButton_mini: mini,
mx_SSOButton_default: !idp,
mx_SSOButton_primary: primary,
},
brandPart,
);
if (mini) {
// TODO fallback icon
@ -128,14 +148,15 @@ const SSOButton: React.FC<ISSOButtonProps> = ({
interface IProps {
matrixClient: MatrixClient;
flow: ISSOFlow;
loginType?: "sso" | "cas";
loginType: "sso" | "cas";
fragmentAfterLogin?: string;
primary?: boolean;
action?: SSOAction;
}
const MAX_PER_ROW = 6;
const SSOButtons: React.FC<IProps> = ({ matrixClient, flow, loginType, fragmentAfterLogin, primary }) => {
const SSOButtons: React.FC<IProps> = ({ matrixClient, flow, loginType, fragmentAfterLogin, primary, action }) => {
const providers = flow.identity_providers || [];
if (providers.length < 2) {
return (
@ -146,6 +167,8 @@ const SSOButtons: React.FC<IProps> = ({ matrixClient, flow, loginType, fragmentA
fragmentAfterLogin={fragmentAfterLogin}
idp={providers[0]}
primary={primary}
action={action}
flow={flow}
/>
</div>
);
@ -167,6 +190,8 @@ const SSOButtons: React.FC<IProps> = ({ matrixClient, flow, loginType, fragmentA
idp={idp}
mini={true}
primary={primary}
action={action}
flow={flow}
/>
))}
</div>