mirror of
https://github.com/cinnyapp/cinny.git
synced 2024-12-29 10:56:10 +00:00
fix sso login without identity providers (#1934)
This commit is contained in:
parent
c6a8fb1117
commit
09444f9e08
|
@ -1,16 +1,10 @@
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { ILoginFlow, IPasswordFlow, ISSOFlow, LoginFlow } from 'matrix-js-sdk/lib/@types/auth';
|
import { ILoginFlow, IPasswordFlow, ISSOFlow, LoginFlow } from 'matrix-js-sdk/lib/@types/auth';
|
||||||
import { WithRequiredProp } from '../../types/utils';
|
|
||||||
|
|
||||||
export type Required_SSOFlow = WithRequiredProp<ISSOFlow, 'identity_providers'>;
|
export const getSSOFlow = (loginFlows: LoginFlow[]): ISSOFlow | undefined =>
|
||||||
export const getSSOFlow = (loginFlows: LoginFlow[]): Required_SSOFlow | undefined =>
|
loginFlows.find((flow) => flow.type === 'm.login.sso' || flow.type === 'm.login.cas') as
|
||||||
loginFlows.find(
|
| ISSOFlow
|
||||||
(flow) =>
|
| undefined;
|
||||||
(flow.type === 'm.login.sso' || flow.type === 'm.login.cas') &&
|
|
||||||
'identity_providers' in flow &&
|
|
||||||
Array.isArray(flow.identity_providers) &&
|
|
||||||
flow.identity_providers.length > 0
|
|
||||||
) as Required_SSOFlow | undefined;
|
|
||||||
|
|
||||||
export const getPasswordFlow = (loginFlows: LoginFlow[]): IPasswordFlow | undefined =>
|
export const getPasswordFlow = (loginFlows: LoginFlow[]): IPasswordFlow | undefined =>
|
||||||
loginFlows.find((flow) => flow.type === 'm.login.password') as IPasswordFlow;
|
loginFlows.find((flow) => flow.type === 'm.login.password') as IPasswordFlow;
|
||||||
|
@ -22,7 +16,7 @@ export const getTokenFlow = (loginFlows: LoginFlow[]): LoginFlow | undefined =>
|
||||||
export type ParsedLoginFlows = {
|
export type ParsedLoginFlows = {
|
||||||
password?: LoginFlow;
|
password?: LoginFlow;
|
||||||
token?: LoginFlow;
|
token?: LoginFlow;
|
||||||
sso?: Required_SSOFlow;
|
sso?: ISSOFlow;
|
||||||
};
|
};
|
||||||
export const useParsedLoginFlows = (loginFlows: LoginFlow[]) => {
|
export const useParsedLoginFlows = (loginFlows: LoginFlow[]) => {
|
||||||
const parsedFlow: ParsedLoginFlows = useMemo<ParsedLoginFlows>(
|
const parsedFlow: ParsedLoginFlows = useMemo<ParsedLoginFlows>(
|
||||||
|
|
|
@ -4,69 +4,89 @@ import React, { useMemo } from 'react';
|
||||||
import { useAutoDiscoveryInfo } from '../../hooks/useAutoDiscoveryInfo';
|
import { useAutoDiscoveryInfo } from '../../hooks/useAutoDiscoveryInfo';
|
||||||
|
|
||||||
type SSOLoginProps = {
|
type SSOLoginProps = {
|
||||||
providers: IIdentityProvider[];
|
providers?: IIdentityProvider[];
|
||||||
asIcons?: boolean;
|
|
||||||
redirectUrl: string;
|
redirectUrl: string;
|
||||||
|
saveScreenSpace?: boolean;
|
||||||
};
|
};
|
||||||
export function SSOLogin({ providers, redirectUrl, asIcons }: SSOLoginProps) {
|
export function SSOLogin({ providers, redirectUrl, saveScreenSpace }: SSOLoginProps) {
|
||||||
const discovery = useAutoDiscoveryInfo();
|
const discovery = useAutoDiscoveryInfo();
|
||||||
const baseUrl = discovery['m.homeserver'].base_url;
|
const baseUrl = discovery['m.homeserver'].base_url;
|
||||||
const mx = useMemo(() => createClient({ baseUrl }), [baseUrl]);
|
const mx = useMemo(() => createClient({ baseUrl }), [baseUrl]);
|
||||||
|
|
||||||
const getSSOIdUrl = (ssoId: string): string => mx.getSsoLoginUrl(redirectUrl, 'sso', ssoId);
|
const getSSOIdUrl = (ssoId?: string): string => mx.getSsoLoginUrl(redirectUrl, 'sso', ssoId);
|
||||||
|
|
||||||
const anyAsBtn = providers.find(
|
const withoutIcon = providers
|
||||||
(provider) => !provider.icon || !mx.mxcUrlToHttp(provider.icon, 96, 96, 'crop', false)
|
? providers.find(
|
||||||
);
|
(provider) => !provider.icon || !mx.mxcUrlToHttp(provider.icon, 96, 96, 'crop', false)
|
||||||
|
)
|
||||||
|
: true;
|
||||||
|
|
||||||
|
const renderAsIcons = withoutIcon ? false : saveScreenSpace && providers && providers.length > 2;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box justifyContent="Center" gap="600" wrap="Wrap">
|
<Box justifyContent="Center" gap="600" wrap="Wrap">
|
||||||
{providers.map((provider) => {
|
{providers ? (
|
||||||
const { id, name, icon } = provider;
|
providers.map((provider) => {
|
||||||
const iconUrl = icon && mx.mxcUrlToHttp(icon, 96, 96, 'crop', false);
|
const { id, name, icon } = provider;
|
||||||
|
const iconUrl = icon && mx.mxcUrlToHttp(icon, 96, 96, 'crop', false);
|
||||||
|
|
||||||
const buttonTitle = `Continue with ${name}`;
|
const buttonTitle = `Continue with ${name}`;
|
||||||
|
|
||||||
|
if (renderAsIcons) {
|
||||||
|
return (
|
||||||
|
<Avatar
|
||||||
|
style={{ cursor: 'pointer' }}
|
||||||
|
key={id}
|
||||||
|
as="a"
|
||||||
|
href={getSSOIdUrl(id)}
|
||||||
|
aria-label={buttonTitle}
|
||||||
|
size="300"
|
||||||
|
radii="300"
|
||||||
|
>
|
||||||
|
<AvatarImage src={iconUrl!} alt={name} title={buttonTitle} />
|
||||||
|
</Avatar>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (!anyAsBtn && iconUrl && asIcons) {
|
|
||||||
return (
|
return (
|
||||||
<Avatar
|
<Button
|
||||||
style={{ cursor: 'pointer' }}
|
style={{ width: '100%' }}
|
||||||
key={id}
|
key={id}
|
||||||
as="a"
|
as="a"
|
||||||
href={getSSOIdUrl(id)}
|
href={getSSOIdUrl(id)}
|
||||||
aria-label={buttonTitle}
|
size="500"
|
||||||
size="300"
|
variant="Secondary"
|
||||||
radii="300"
|
fill="Soft"
|
||||||
|
outlined
|
||||||
|
before={
|
||||||
|
iconUrl && (
|
||||||
|
<Avatar size="200" radii="300">
|
||||||
|
<AvatarImage src={iconUrl} alt={name} />
|
||||||
|
</Avatar>
|
||||||
|
)
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<AvatarImage src={iconUrl} alt={name} title={buttonTitle} />
|
<Text align="Center" size="B500" truncate>
|
||||||
</Avatar>
|
{buttonTitle}
|
||||||
|
</Text>
|
||||||
|
</Button>
|
||||||
);
|
);
|
||||||
}
|
})
|
||||||
|
) : (
|
||||||
return (
|
<Button
|
||||||
<Button
|
style={{ width: '100%' }}
|
||||||
style={{ width: '100%' }}
|
as="a"
|
||||||
key={id}
|
href={getSSOIdUrl()}
|
||||||
as="a"
|
size="500"
|
||||||
href={getSSOIdUrl(id)}
|
variant="Secondary"
|
||||||
size="500"
|
fill="Soft"
|
||||||
variant="Secondary"
|
outlined
|
||||||
fill="Soft"
|
>
|
||||||
outlined
|
<Text align="Center" size="B500" truncate>
|
||||||
before={
|
Continue with SSO
|
||||||
iconUrl && (
|
</Text>
|
||||||
<Avatar size="200" radii="300">
|
</Button>
|
||||||
<AvatarImage src={iconUrl} alt={name} />
|
)}
|
||||||
</Avatar>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Text align="Center" size="B500" truncate>
|
|
||||||
{buttonTitle}
|
|
||||||
</Text>
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,9 +76,7 @@ export function Login() {
|
||||||
<SSOLogin
|
<SSOLogin
|
||||||
providers={parsedFlows.sso.identity_providers}
|
providers={parsedFlows.sso.identity_providers}
|
||||||
redirectUrl={ssoRedirectUrl}
|
redirectUrl={ssoRedirectUrl}
|
||||||
asIcons={
|
saveScreenSpace={parsedFlows.password !== undefined}
|
||||||
parsedFlows.password !== undefined && parsedFlows.sso.identity_providers.length > 2
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<span data-spacing-node />
|
<span data-spacing-node />
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -83,10 +83,7 @@ export function Register() {
|
||||||
<SSOLogin
|
<SSOLogin
|
||||||
providers={sso.identity_providers}
|
providers={sso.identity_providers}
|
||||||
redirectUrl={ssoRedirectUrl}
|
redirectUrl={ssoRedirectUrl}
|
||||||
asIcons={
|
saveScreenSpace={registerFlows.status === RegisterFlowStatus.FlowRequired}
|
||||||
registerFlows.status === RegisterFlowStatus.FlowRequired &&
|
|
||||||
sso.identity_providers.length > 2
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<span data-spacing-node />
|
<span data-spacing-node />
|
||||||
</>
|
</>
|
||||||
|
|
Loading…
Reference in a new issue