add idps to invite flow

This commit is contained in:
Max Peintner
2024-12-20 11:14:03 +01:00
parent 0f4d31eec7
commit 3887e26896
4 changed files with 46 additions and 40 deletions

View File

@@ -2,10 +2,12 @@ import { Alert } from "@/components/alert";
import { BackButton } from "@/components/back-button"; import { BackButton } from "@/components/back-button";
import { ChooseAuthenticatorToSetup } from "@/components/choose-authenticator-to-setup"; import { ChooseAuthenticatorToSetup } from "@/components/choose-authenticator-to-setup";
import { DynamicTheme } from "@/components/dynamic-theme"; import { DynamicTheme } from "@/components/dynamic-theme";
import { SignInWithIdp } from "@/components/sign-in-with-idp";
import { UserAvatar } from "@/components/user-avatar"; import { UserAvatar } from "@/components/user-avatar";
import { getSessionCookieById } from "@/lib/cookies"; import { getSessionCookieById } from "@/lib/cookies";
import { loadMostRecentSession } from "@/lib/session"; import { loadMostRecentSession } from "@/lib/session";
import { import {
getActiveIdentityProviders,
getBrandingSettings, getBrandingSettings,
getLoginSettings, getLoginSettings,
getSession, getSession,
@@ -86,13 +88,12 @@ export default async function Page(props: {
sessionWithData.factors?.user?.organizationId, sessionWithData.factors?.user?.organizationId,
); );
/* - TODO: Implement after https://github.com/zitadel/zitadel/issues/8981 */ const identityProviders = await getActiveIdentityProviders(
sessionWithData.factors?.user?.organizationId,
// const identityProviders = await getActiveIdentityProviders( true,
// sessionWithData.factors?.user?.organizationId, ).then((resp) => {
// ).then((resp) => { return resp.identityProviders;
// return resp.identityProviders; });
// });
const params = new URLSearchParams({ const params = new URLSearchParams({
initial: "true", // defines that a code is not required and is therefore not shown in the UI initial: "true", // defines that a code is not required and is therefore not shown in the UI
@@ -110,10 +111,6 @@ export default async function Page(props: {
params.set("authRequestId", authRequestId); params.set("authRequestId", authRequestId);
} }
const host = process.env.VERCEL_URL
? `https://${process.env.VERCEL_URL}`
: "http://localhost:3000";
return ( return (
<DynamicTheme branding={branding}> <DynamicTheme branding={branding}>
<div className="flex flex-col items-center space-y-4"> <div className="flex flex-col items-center space-y-4">
@@ -136,21 +133,18 @@ export default async function Page(props: {
></ChooseAuthenticatorToSetup> ></ChooseAuthenticatorToSetup>
)} )}
{/* - TODO: Implement after https://github.com/zitadel/zitadel/issues/8981 */} <p className="ztdl-p text-center">
{/* <p className="ztdl-p text-center">
or sign in with an Identity Provider or sign in with an Identity Provider
</p> </p>
{loginSettings?.allowExternalIdp && identityProviders && ( {loginSettings?.allowExternalIdp && identityProviders && (
<SignInWithIdp <SignInWithIdp
host={host}
identityProviders={identityProviders} identityProviders={identityProviders}
authRequestId={authRequestId} authRequestId={authRequestId}
organization={sessionWithData.factors?.user?.organizationId} organization={sessionWithData.factors?.user?.organizationId}
linkOnly={true} // tell the callback function to just link the IDP and not login, to get an error when user is already available linkOnly={true} // tell the callback function to just link the IDP and not login, to get an error when user is already available
></SignInWithIdp> ></SignInWithIdp>
)} */} )}
<div className="mt-8 flex w-full flex-row items-center"> <div className="mt-8 flex w-full flex-row items-center">
<BackButton /> <BackButton />

View File

@@ -93,6 +93,26 @@ async function linkingSuccess(
); );
} }
async function linkingFailed(branding?: BrandingSettings) {
const locale = getLocale();
const t = await getTranslations({ locale, namespace: "idp" });
return (
<DynamicTheme branding={branding}>
<div className="flex flex-col items-center space-y-4">
<h1>{t("linkingError.title")}</h1>
<div className="w-full">
{
<Alert type={AlertType.ALERT}>
{t("linkingError.description")}
</Alert>
}
</div>
</div>
</DynamicTheme>
);
}
export default async function Page(props: { export default async function Page(props: {
searchParams: Promise<Record<string | number | symbol, string | undefined>>; searchParams: Promise<Record<string | number | symbol, string | undefined>>;
params: Promise<{ provider: string }>; params: Promise<{ provider: string }>;
@@ -174,20 +194,7 @@ export default async function Page(props: {
}, },
foundUser.userId, foundUser.userId,
).catch((error) => { ).catch((error) => {
return ( return linkingFailed(branding);
<DynamicTheme branding={branding}>
<div className="flex flex-col items-center space-y-4">
<h1>{t("linkingError.title")}</h1>
<div className="w-full">
{
<Alert type={AlertType.ALERT}>
{t("linkingError.description")}
</Alert>
}
</div>
</div>
</DynamicTheme>
);
}); });
if (idpLink) { if (idpLink) {
@@ -201,7 +208,8 @@ export default async function Page(props: {
} }
} }
if (options?.isCreationAllowed && options.isAutoCreation) { // if link === true, do not create user
if (options?.isCreationAllowed && options.isAutoCreation && !link) {
let orgToRegisterOn: string | undefined = organization; let orgToRegisterOn: string | undefined = organization;
let userData: AddHumanUserRequest = let userData: AddHumanUserRequest =
@@ -256,6 +264,10 @@ export default async function Page(props: {
} }
} }
if (link) {
return linkingFailed(branding);
}
// return login failed if no linking or creation is allowed and no user was found // return login failed if no linking or creation is allowed and no user was found
return loginFailed(branding, "No user found"); return loginFailed(branding, "No user found");
} }

View File

@@ -70,11 +70,7 @@ export function SignInWithIdp({
const renderIDPButton = (idp: IdentityProvider) => { const renderIDPButton = (idp: IdentityProvider) => {
const { id, name, type } = idp; const { id, name, type } = idp;
const onClick = () => startFlow(id, idpTypeToSlug(type)); const onClick = () => startFlow(id, idpTypeToSlug(type));
/* - TODO: Implement after https://github.com/zitadel/zitadel/issues/8981 */
// .filter((idp) =>
// linkOnly ? idp.config?.options.isLinkingAllowed : true,
// )
const components: Partial< const components: Partial<
Record< Record<
IdentityProviderType, IdentityProviderType,

View File

@@ -633,11 +633,15 @@ export async function verifyU2FRegistration(
return userService.verifyU2FRegistration(request, {}); return userService.verifyU2FRegistration(request, {});
} }
export async function getActiveIdentityProviders(orgId?: string) { export async function getActiveIdentityProviders(
return settingsService.getActiveIdentityProviders( orgId?: string,
{ ctx: makeReqCtx(orgId) }, linking_allowed?: boolean,
{}, ) {
); const props: any = { ctx: makeReqCtx(orgId) };
if (linking_allowed) {
props.linkingAllowed = linking_allowed;
}
return settingsService.getActiveIdentityProviders(props, {});
} }
/** /**