mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-18 05:52:51 +00:00
fix(login): remove loginSettings.allowRegister check for IDPs (#11731)
Closes #11138 # Which Problems Are Solved Previously, the application strictly checked the allowRegister setting—which typically applies to local account creation—before considering if a user without an account should be redirected to an IDP, or whether they could access the register page. This blocked users from registering via identity providers when local registration was disabled but IDPs were configured. # How the Problems Are Solved - Removed the allowRegister dependency when deciding to redirect an unknown user to an IDP. The logic now only checks !allowLocalAuthentication, correctly opening up the IDP registration flow even when local auth/registration is not allowed. - Modified the block condition so the register page is only restricted if allowRegister is false and there are no configured identityProviders available.
This commit is contained in:
@@ -55,7 +55,23 @@ export default async function Page(props: { searchParams: Promise<Record<string
|
||||
});
|
||||
});
|
||||
|
||||
if (!loginSettings?.allowRegister) {
|
||||
if (!loginSettings) {
|
||||
return (
|
||||
<DynamicTheme branding={branding}>
|
||||
<div className="flex flex-col space-y-4">
|
||||
<h1>
|
||||
<Translated i18nKey="title" namespace="register" />
|
||||
</h1>
|
||||
<Alert>
|
||||
<Translated i18nKey="unknownContext" namespace="error" />
|
||||
</Alert>
|
||||
</div>
|
||||
<div className="w-full"></div>
|
||||
</DynamicTheme>
|
||||
);
|
||||
}
|
||||
|
||||
if (!loginSettings?.allowRegister && (!loginSettings.allowExternalIdp || identityProviders.length === 0)) {
|
||||
return (
|
||||
<DynamicTheme branding={branding}>
|
||||
<div className="flex flex-col space-y-4">
|
||||
|
||||
@@ -276,7 +276,7 @@ describe("sendLoginname", () => {
|
||||
});
|
||||
mockListIDPLinks.mockResolvedValue({ result: [] });
|
||||
mockGetActiveIdentityProviders.mockResolvedValue({
|
||||
identityProviders: [{ id: "org-idp-123", type: 0 }],
|
||||
identityProviders: [{ id: "org-idp-123", type: 0, options: { isAutoCreation: true } }],
|
||||
});
|
||||
mockIdpTypeToSlug.mockReturnValue("google");
|
||||
mockStartIdentityProviderFlow.mockResolvedValue({ url: "https://org-idp.example.com/auth" });
|
||||
@@ -469,7 +469,7 @@ describe("sendLoginname", () => {
|
||||
allowLocalAuthentication: false,
|
||||
});
|
||||
mockGetActiveIdentityProviders.mockResolvedValue({
|
||||
identityProviders: [{ id: "idp123", type: "OIDC" }],
|
||||
identityProviders: [{ id: "idp123", type: "OIDC", options: { isAutoCreation: true } }],
|
||||
});
|
||||
mockStartIdentityProviderFlow.mockResolvedValue({ url: "https://idp.example.com/auth" });
|
||||
|
||||
@@ -503,6 +503,7 @@ describe("sendLoginname", () => {
|
||||
test("should redirect to password when ignoreUnknownUsernames is true", async () => {
|
||||
mockGetLoginSettings.mockResolvedValue({
|
||||
ignoreUnknownUsernames: true,
|
||||
allowLocalAuthentication: true,
|
||||
});
|
||||
|
||||
const result = await sendLoginname({
|
||||
@@ -532,6 +533,39 @@ describe("sendLoginname", () => {
|
||||
expect(result).toEqual({ error: "errors.userNotFound" });
|
||||
});
|
||||
|
||||
test("should redirect to IDP when allowRegister: false, allowLocalAuthentication: false and a single active IDP exists", async () => {
|
||||
mockGetLoginSettings.mockResolvedValue({
|
||||
allowRegister: false,
|
||||
allowLocalAuthentication: false,
|
||||
});
|
||||
mockGetActiveIdentityProviders.mockResolvedValue({
|
||||
identityProviders: [{ id: "idp123", type: "OIDC", options: { isAutoCreation: true } }],
|
||||
});
|
||||
mockStartIdentityProviderFlow.mockResolvedValue({ url: "https://idp.example.com/auth" });
|
||||
|
||||
const result = await sendLoginname({
|
||||
loginName: "[email protected]",
|
||||
});
|
||||
|
||||
expect(result).toEqual({ redirect: "https://idp.example.com/auth" });
|
||||
});
|
||||
|
||||
test("should not redirect to IDP when single active IDP does not allow creation", async () => {
|
||||
mockGetLoginSettings.mockResolvedValue({
|
||||
allowRegister: false,
|
||||
allowLocalAuthentication: false,
|
||||
});
|
||||
mockGetActiveIdentityProviders.mockResolvedValue({
|
||||
identityProviders: [{ id: "idp123", type: "OIDC", options: { isAutoCreation: false, isCreationAllowed: false } }],
|
||||
});
|
||||
|
||||
const result = await sendLoginname({
|
||||
loginName: "[email protected]",
|
||||
});
|
||||
|
||||
expect(result).toEqual({ error: "errors.userNotFound" });
|
||||
});
|
||||
|
||||
test("should discover organization from domain suffix when user not found without org context", async () => {
|
||||
// Mock login settings for instance level (no org context)
|
||||
mockGetLoginSettings
|
||||
@@ -592,7 +626,7 @@ describe("sendLoginname", () => {
|
||||
});
|
||||
|
||||
mockGetActiveIdentityProviders.mockResolvedValue({
|
||||
identityProviders: [{ id: "idp123", type: "OIDC" }],
|
||||
identityProviders: [{ id: "idp123", type: "OIDC", options: { isAutoCreation: true } }],
|
||||
});
|
||||
mockStartIdentityProviderFlow.mockResolvedValue({ url: "https://idp.example.com/auth?org=discovered-org-456" });
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
|
||||
// If no IDP links exist for the user (or no userId provided), try to get active IDPs from the organization
|
||||
if (identityProviders.length === 0) {
|
||||
const activeIdps = await getActiveIdentityProviders({ serviceConfig, orgId: organization }).then((resp) => {
|
||||
return resp.identityProviders;
|
||||
return resp.identityProviders.filter((idp) => idp.options?.isAutoCreation || idp.options?.isCreationAllowed);
|
||||
});
|
||||
|
||||
// If exactly one active IDP exists in the organization, redirect to it
|
||||
@@ -525,8 +525,9 @@ export async function sendLoginname(command: SendLoginnameCommand) {
|
||||
}
|
||||
}
|
||||
|
||||
// user not found, check if register is enabled on instance / organization context
|
||||
if (effectiveLoginSettings?.allowRegister && !effectiveLoginSettings?.allowLocalAuthentication) {
|
||||
// user not found, check if IDPs are available when local auth is not allowed
|
||||
if (!effectiveLoginSettings?.allowLocalAuthentication) {
|
||||
console.log("redirecting to IDP (register allowed, password not allowed)");
|
||||
logger.debug("redirecting to IDP (register allowed, password not allowed)");
|
||||
const resp = await redirectUserToIDP(undefined, discoveredOrganization);
|
||||
if (resp) {
|
||||
|
||||
Reference in New Issue
Block a user