mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-11 00:25:12 +00:00
feat(login): Sign in with Zitadel (#12530)
Closes #11824 # Which Problems Are Solved The backend supports the dedicated ZITADEL identity provider template (`AddZitadelProvider`, `IDENTITY_PROVIDER_TYPE_ZITADEL`), but the new login (login v2) cannot yet handle providers of this type: A configured and activated ZITADEL IdP is not rendered as a sign-in option, because the provider type is missing from the login's component mapping. # How the Problems Are Solved - Regenerated `@zitadel/proto` (`settings/v2/login_settings_pb` in `types`, `es` and `cjs`) so `IdentityProviderType.ZITADEL = 13` is available (`idp/v2` was already up to date). - `apps/login/src/lib/idp.ts`: - `idpTypeToSlug` maps `ZITADEL` to the `zitadel` slug, used by the generic `/idp/[provider]/process|failure` routes (no route changes needed). - `idpTypeToIdentityProviderType` maps `IDPType.IDP_TYPE_ZITADEL` to `IdentityProviderType.ZITADEL`. - Added `SignInWithZitadel` button (`apps/login/src/components/idps/sign-in-with-zitadel.tsx`) with the Zitadel logo as inline SVG: the brand gradient is theme-independent, accents use `currentColor` to adapt to light/dark, consistent with the other provider buttons. - Registered the Zitadel type in the provider-to-component mapping in `sign-in-with-idp.tsx`. No changes to the IdP intent handling are required: user auto-creation/auto-update consume the pre-mapped `user_action.create_user` / `update_user` from `RetrieveIdentityProviderIntent`, which the backend fills for the Zitadel provider like for any generic OIDC provider. # Additional Changes - Added the `signInWithZitadel` i18n key ("Sign in with Zitadel") to all 15 locale files. - Extended `idp.test.ts` with the new slug and type mappings and added the Zitadel type to the exhaustive enum-coverage tests (45 tests passing). # Additional Context - Part of the "Zitadel as an Identity Provider" epic: #5127 - Enables the customer-portal "support access" flow, where support staff sign in to a customer instance via a pre-configured Zitadel Support IdP --------- Co-authored-by: Copilot Autofix powered by AI <[email protected]>
This commit is contained in:
co-authored by
Copilot Autofix powered by AI
parent
83854e80e0
commit
30434d176c
@@ -0,0 +1,187 @@
|
||||
"use client";
|
||||
|
||||
import { forwardRef, useId } from "react";
|
||||
import { Translated } from "../translated";
|
||||
import { BaseButton, SignInWithIdentityProviderProps } from "./base-button";
|
||||
|
||||
export const SignInWithZitadel = forwardRef<HTMLButtonElement, SignInWithIdentityProviderProps>(
|
||||
function SignInWithZitadel(props, ref) {
|
||||
const { children, name, ...restProps } = props;
|
||||
// Unique per component instance: multiple ZITADEL IdPs can be rendered on
|
||||
// the same page, and duplicate SVG gradient ids would be invalid HTML.
|
||||
const gradientId = useId().replace(/:/g, "");
|
||||
|
||||
return (
|
||||
<BaseButton {...restProps} ref={ref}>
|
||||
<div className="flex h-12 w-12 items-center justify-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={24}
|
||||
height={24}
|
||||
viewBox="0 0 467 467"
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
aria-hidden="true"
|
||||
focusable="false"
|
||||
>
|
||||
<g transform="matrix(0.564847,0,0,0.659318,-1282.85,0)">
|
||||
<g transform="matrix(4.96737,-1.14029,1.331,4.25561,-5923.46,-2258.26)">
|
||||
<path
|
||||
d="M1493.5,1056.38L1493.5,1037L1496.5,1037L1496.5,1061.62L1426.02,1020.38L1496.5,979.392L1496.5,1004L1493.5,1004L1493.5,984.608L1431.98,1020.39L1493.5,1056.38Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</g>
|
||||
<g transform="matrix(31.0036,0,0,15.0393,-397275,-666.457)">
|
||||
<g transform="matrix(-0.0429306,-0.282967,0.160219,-0.0758207,12884.5,137.392)">
|
||||
<path
|
||||
d="M212.517,110L200.392,110L190,92L179.608,110L167.483,110L190,71L212.517,110Z"
|
||||
fill={`url(#${gradientId}-g1)`}
|
||||
/>
|
||||
</g>
|
||||
<g transform="matrix(0.160219,0.0758207,-0.0429306,0.282967,12878.9,10.8747)">
|
||||
<path
|
||||
d="M212.517,110L200.392,110L190,92L179.608,110L167.483,110L190,71L212.517,110Z"
|
||||
fill={`url(#${gradientId}-g2)`}
|
||||
/>
|
||||
</g>
|
||||
<g transform="matrix(-0.117289,0.207146,-0.117289,-0.207146,12943.8,65.7)">
|
||||
<path
|
||||
d="M212.517,110L200.392,110L190,92L179.608,110L167.483,110L190,71L212.517,110Z"
|
||||
fill={`url(#${gradientId}-g3)`}
|
||||
/>
|
||||
</g>
|
||||
<g transform="matrix(-0.160219,-0.0758207,0.0429306,-0.282967,12917.4,132.195)">
|
||||
<path d="M139.622,117L149,142L130.244,142L139.622,117Z" fill={`url(#${gradientId}-g4)`} />
|
||||
</g>
|
||||
<g transform="matrix(-0.117289,0.207146,0.117289,0.207146,12897.8,5.87512)">
|
||||
<path d="M139.622,117L149,142L130.244,142L139.622,117Z" fill={`url(#${gradientId}-g5)`} />
|
||||
</g>
|
||||
<g transform="matrix(-0.0429306,-0.282967,-0.160219,0.0758207,12936.8,97.6441)">
|
||||
<path d="M139.622,117L149,142L130.244,142L139.622,117Z" fill={`url(#${gradientId}-g6)`} />
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(4.96737,-1.14029,1.331,4.25561,-5928.43,-2257.12)">
|
||||
<circle cx="1496" cy="1004" r="7" fill="currentColor" />
|
||||
</g>
|
||||
<g transform="matrix(4.96737,-1.14029,1.331,4.25561,-5884.5,-2116.69)">
|
||||
<circle cx="1496" cy="1004" r="7" fill="currentColor" />
|
||||
</g>
|
||||
<g transform="matrix(4.96737,-1.14029,1.331,4.25561,-5855.22,-2023.06)">
|
||||
<circle cx="1496" cy="1004" r="7" fill="currentColor" />
|
||||
</g>
|
||||
<g transform="matrix(4.96737,-1.14029,1.331,4.25561,-6234.47,-2112.14)">
|
||||
<circle cx="1496" cy="1004" r="7" fill="currentColor" />
|
||||
</g>
|
||||
<g transform="matrix(4.96737,-1.14029,1.331,4.25561,-5957.71,-2350.75)">
|
||||
<circle cx="1496" cy="1004" r="7" fill="currentColor" />
|
||||
</g>
|
||||
<g transform="matrix(4.96737,-1.14029,1.16463,3.72366,-5477.99,-831.33)">
|
||||
<path
|
||||
d="M1499.26,757.787C1499.26,757.787 1497.37,756.489 1497,755.2C1496.71,754.182 1496.57,750.662 1496.54,750C1496.41,747.303 1499.21,745.644 1499.21,745.644L1490.01,745.835C1490.01,745.835 1493.15,745.713 1493.46,750C1493.51,750.661 1493.23,753.476 1493,755.2C1492.91,756.447 1491.2,757.668 1491.2,757.668L1499.26,757.787Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</g>
|
||||
<g transform="matrix(4.96737,-1.14029,1.16463,3.72366,-5404.79,-597.271)">
|
||||
<path
|
||||
d="M1498.27,757.077C1498.27,757.077 1496.71,756.46 1496.65,754.8C1496.65,753.658 1496.64,753.281 1496.65,752.016C1496.62,751.334 1496.59,750.608 1496.65,749.949C1496.78,746.836 1498.5,746.156 1498.5,746.156L1491.46,745.931C1491.46,745.931 1493.37,746.719 1493.65,749.83C1493.71,750.489 1493.69,751.528 1493.65,752.209C1493.64,753.331 1493.64,753.413 1493.65,754.518C1493.68,756.334 1492.58,756.827 1492.58,756.827L1498.27,757.077Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</g>
|
||||
<g transform="matrix(4.96737,-1.14029,1.16463,3.72366,-5770.62,-677.495)">
|
||||
<path
|
||||
d="M1500.86,762.056C1500.86,762.056 1499.86,760.4 1503.09,757.456C1504.91,755.797 1507.33,754.151 1509.98,752.255C1514.82,748.79 1520.68,744.94 1526.52,741.049C1531.45,737.766 1536.38,734.479 1540.82,731.68C1544.52,729.349 1547.85,727.296 1550.54,725.8C1551.07,725.506 1551.6,725.329 1552.05,725.029C1554.73,723.257 1556.85,724.968 1556.85,724.968L1552.23,716.282C1552.23,716.282 1551.99,719.454 1550,720.997C1549.57,721.333 1549.15,721.741 1548.67,722.12C1546.2,724.053 1542.99,726.344 1539.39,728.867C1535.06,731.898 1530.13,735.166 1525.19,738.438C1519.35,742.314 1513.52,746.234 1508.49,749.329C1505.74,751.023 1503.28,752.577 1501.13,753.598C1497.99,755.086 1495.28,753.617 1495.28,753.617L1500.86,762.056Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</g>
|
||||
<g transform="matrix(4.96737,-1.14029,-1.16463,-3.72366,-3997,4993.28)">
|
||||
<path
|
||||
d="M1496.1,754.362C1496.1,754.362 1497.2,755.607 1501.13,753.598C1503.25,752.509 1505.74,751.023 1508.49,749.329C1513.52,746.234 1519.35,742.314 1525.19,738.438C1530.13,735.166 1534.94,731.832 1539.27,728.802C1542.87,726.279 1549.36,722.059 1549.81,721.75C1552.75,719.73 1552.18,718.196 1552.18,718.196L1555.28,724.152C1555.28,724.152 1553.77,722.905 1551.37,724.681C1550.93,725.006 1544.52,729.349 1540.82,731.68C1536.38,734.479 1531.45,737.766 1526.52,741.049C1520.68,744.94 1514.82,748.79 1509.98,752.255C1507.33,754.151 1504.89,755.771 1503.09,757.456C1499.47,760.841 1501.26,763.283 1501.26,763.283L1496.1,754.362Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id={`${gradientId}-g1`}
|
||||
x1="0"
|
||||
y1="0"
|
||||
x2="1"
|
||||
y2="0"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-41.5984,155.247,-155.247,-41.5984,201.516,76.8392)"
|
||||
>
|
||||
<stop offset="0" stopColor="rgb(255,143,0)" stopOpacity={1} />
|
||||
<stop offset="1" stopColor="rgb(254,0,255)" stopOpacity={1} />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id={`${gradientId}-g2`}
|
||||
x1="0"
|
||||
y1="0"
|
||||
x2="1"
|
||||
y2="0"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(155.247,-41.5984,41.5984,155.247,110.08,195.509)"
|
||||
>
|
||||
<stop offset="0" stopColor="rgb(255,143,0)" stopOpacity={1} />
|
||||
<stop offset="1" stopColor="rgb(254,0,255)" stopOpacity={1} />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id={`${gradientId}-g3`}
|
||||
x1="0"
|
||||
y1="0"
|
||||
x2="1"
|
||||
y2="0"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-113.649,-113.649,113.649,-113.649,258.31,215.618)"
|
||||
>
|
||||
<stop offset="0" stopColor="rgb(255,143,0)" stopOpacity={1} />
|
||||
<stop offset="1" stopColor="rgb(254,0,255)" stopOpacity={1} />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id={`${gradientId}-g4`}
|
||||
x1="0"
|
||||
y1="0"
|
||||
x2="1"
|
||||
y2="0"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-155.247,41.5984,-41.5984,-155.247,220.914,144.546)"
|
||||
>
|
||||
<stop offset="0" stopColor="rgb(255,143,0)" stopOpacity={1} />
|
||||
<stop offset="1" stopColor="rgb(254,0,255)" stopOpacity={1} />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id={`${gradientId}-g5`}
|
||||
x1="0"
|
||||
y1="0"
|
||||
x2="1"
|
||||
y2="0"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-113.649,113.649,113.649,113.649,206.837,124.661)"
|
||||
>
|
||||
<stop offset="0" stopColor="rgb(255,143,0)" stopOpacity={1} />
|
||||
<stop offset="1" stopColor="rgb(254,0,255)" stopOpacity={1} />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id={`${gradientId}-g6`}
|
||||
x1="0"
|
||||
y1="0"
|
||||
x2="1"
|
||||
y2="0"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-41.5984,-155.247,-155.247,41.5984,152.054,262.8)"
|
||||
>
|
||||
<stop offset="0" stopColor="rgb(255,143,0)" stopOpacity={1} />
|
||||
<stop offset="1" stopColor="rgb(254,0,255)" stopOpacity={1} />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
</div>
|
||||
{children ? (
|
||||
children
|
||||
) : (
|
||||
<span className="ml-4">{name ? name : <Translated i18nKey="signInWithZitadel" namespace="idp" />}</span>
|
||||
)}
|
||||
</BaseButton>
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -13,6 +13,7 @@ import { SignInWithGeneric } from "./idps/sign-in-with-generic";
|
||||
import { SignInWithGithub } from "./idps/sign-in-with-github";
|
||||
import { SignInWithGitlab } from "./idps/sign-in-with-gitlab";
|
||||
import { SignInWithGoogle } from "./idps/sign-in-with-google";
|
||||
import { SignInWithZitadel } from "./idps/sign-in-with-zitadel";
|
||||
import { Translated } from "./translated";
|
||||
|
||||
export interface SignInWithIDPProps {
|
||||
@@ -51,6 +52,7 @@ export function SignInWithIdp({
|
||||
[IdentityProviderType.SAML]: SignInWithGeneric,
|
||||
[IdentityProviderType.LDAP]: SignInWithGeneric,
|
||||
[IdentityProviderType.JWT]: SignInWithGeneric,
|
||||
[IdentityProviderType.ZITADEL]: SignInWithZitadel,
|
||||
};
|
||||
|
||||
const Component = components[type];
|
||||
|
||||
Reference in New Issue
Block a user