fix(login): fallback for idp login (#10876)

Closes #10671

# Which Problems Are Solved

Users with password authentication disabled in their organization were
seeing "Username Password not allowed!" error instead of being
redirected to their organization's configured Identity Provider. This
affected domain discovery and multi-tenancy use cases in Login V2.

# How the Problems Are Solved

- Updated `redirectUserToIDP` to accept optional `userId` and
`organization` parameters
- Added fallback logic to check organization-level IDPs via
`getActiveIdentityProviders`
- Updated all call sites to pass appropriate organization context
- Added test coverage for the fallback behavior

# Additional Changes

- Consolidated duplicate logic by removing
`redirectUserToSingleIDPIfAvailable` function, which is now handled by
the unified `redirectUserToIDP` function
- improved error handling on verification page

---------

Co-authored-by: Ramon <[email protected]>
This commit is contained in:
Max Peintner
2025-10-21 11:04:33 +02:00
committed by GitHub
co-authored by Ramon
parent 2ad5cf141f
commit ff869482b1
13 changed files with 175 additions and 112 deletions
@@ -1,7 +1,4 @@
import {
LoginSettings,
PasskeysType,
} from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
import { LoginSettings, PasskeysType } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
import { Alert, AlertType } from "./alert";
import { PASSKEYS, PASSWORD } from "./auth-methods";
@@ -13,11 +10,7 @@ type Props = {
loginSettings: LoginSettings;
};
export function ChooseAuthenticatorToSetup({
authMethods,
params,
loginSettings,
}: Props) {
export function ChooseAuthenticatorToSetup({ authMethods, params, loginSettings }: Props) {
if (authMethods.length !== 0) {
return (
<Alert type={AlertType.ALERT}>
@@ -26,26 +19,14 @@ export function ChooseAuthenticatorToSetup({
);
} else {
return (
<>
{loginSettings.passkeysType == PasskeysType.NOT_ALLOWED &&
!loginSettings.allowUsernamePassword && (
<Alert type={AlertType.ALERT}>
<Translated
i18nKey="noMethodsAvailable"
namespace="authenticator"
/>
</Alert>
)}
<div className="grid w-full grid-cols-1 gap-5 pt-4">
{!authMethods.includes(AuthenticationMethodType.PASSWORD) &&
loginSettings.allowUsernamePassword &&
PASSWORD(false, "/password/set?" + params)}
{!authMethods.includes(AuthenticationMethodType.PASSKEY) &&
loginSettings.passkeysType == PasskeysType.ALLOWED &&
PASSKEYS(false, "/passkey/set?" + params)}
</div>
</>
<div className="grid w-full grid-cols-1 gap-5 pt-4">
{!authMethods.includes(AuthenticationMethodType.PASSWORD) &&
loginSettings.allowUsernamePassword &&
PASSWORD(false, "/password/set?" + params)}
{!authMethods.includes(AuthenticationMethodType.PASSKEY) &&
loginSettings.passkeysType == PasskeysType.ALLOWED &&
PASSKEYS(false, "/passkey/set?" + params)}
</div>
);
}
}