diff --git a/apps/login/src/app/api/loginname/route.ts b/apps/login/src/app/api/loginname/route.ts index b6751ae9164..464eddf4e18 100644 --- a/apps/login/src/app/api/loginname/route.ts +++ b/apps/login/src/app/api/loginname/route.ts @@ -2,6 +2,7 @@ import { idpTypeToSlug } from "@/lib/idp"; import { getActiveIdentityProviders, getLoginSettings, + getOrgsByDomain, listAuthenticationMethodTypes, listUsers, startIdentityProviderFlow, @@ -9,6 +10,8 @@ import { import { createSessionForUserIdAndUpdateCookie } from "@/utils/session"; import { NextRequest, NextResponse } from "next/server"; +const ORG_SUFFIX_REGEX = /(?<=@)(.+)/; + export async function POST(request: NextRequest) { const body = await request.json(); if (body) { @@ -104,14 +107,45 @@ export async function POST(request: NextRequest) { loginSettings?.allowRegister && loginSettings?.allowUsernamePassword ) { - const params: any = { organization }; + let orgToRegisterOn: string | undefined = organization; + + if ( + !orgToRegisterOn && + loginName && + ORG_SUFFIX_REGEX.test(loginName) + ) { + const matched = ORG_SUFFIX_REGEX.exec(loginName); + const suffix = matched?.[1] ?? ""; + + // this just returns orgs where the suffix is set as primary domain + const orgs = await getOrgsByDomain(suffix); + const orgToCheckForDiscovery = + orgs.result && orgs.result.length === 1 + ? orgs.result[0].id + : undefined; + + const orgLoginSettings = await getLoginSettings( + orgToCheckForDiscovery, + ); + if (orgLoginSettings?.allowDomainDiscovery) { + orgToRegisterOn = orgToCheckForDiscovery; + } + } + + const params: any = {}; + if (authRequestId) { params.authRequestId = authRequestId; } + if (loginName) { params.email = loginName; } + if (orgToRegisterOn) { + params.organization = orgToRegisterOn; + } + const registerUrl = new URL( "/register?" + new URLSearchParams(params), request.url, diff --git a/apps/login/src/app/login/route.ts b/apps/login/src/app/login/route.ts index cd56d90e5cd..5b992cbebe6 100644 --- a/apps/login/src/app/login/route.ts +++ b/apps/login/src/app/login/route.ts @@ -11,7 +11,7 @@ import { createCallback, getActiveIdentityProviders, getAuthRequest, - getOrgByDomain, + getOrgsByDomain, listSessions, startIdentityProviderFlow, } from "@/lib/zitadel"; @@ -155,8 +155,10 @@ export async function GET(request: NextRequest) { const matched = ORG_DOMAIN_SCOPE_REGEX.exec(orgDomainScope); const orgDomain = matched?.[1] ?? ""; if (orgDomain) { - const org = await getOrgByDomain(orgDomain); - organization = org?.org?.id ?? ""; + const orgs = await getOrgsByDomain(orgDomain); + if (orgs.result && orgs.result.length === 1) { + organization = orgs.result[0].id ?? ""; + } } } } diff --git a/apps/login/src/lib/zitadel.ts b/apps/login/src/lib/zitadel.ts index 73180302e80..bb6603915df 100644 --- a/apps/login/src/lib/zitadel.ts +++ b/apps/login/src/lib/zitadel.ts @@ -5,6 +5,7 @@ import { createUserServiceClient, createIdpServiceClient, makeReqCtx, + createOrganizationServiceClient, } from "@zitadel/client/v2"; import { createManagementServiceClient } from "@zitadel/client/v1"; import { createServerTransport } from "@zitadel/node"; @@ -38,10 +39,10 @@ const transport = createServerTransport( ); export const sessionService = createSessionServiceClient(transport); -export const managementService = createManagementServiceClient(transport); export const userService = createUserServiceClient(transport); export const oidcService = createOIDCServiceClient(transport); export const idpService = createIdpServiceClient(transport); +export const orgService = createOrganizationServiceClient(transport); export const settingsService = createSettingsServiceClient(transport); @@ -295,8 +296,20 @@ export async function listUsers({ return userService.listUsers({ queries: queries }); } -export async function getOrgByDomain(domain: string) { - return managementService.getOrgByDomainGlobal({ domain }, {}); +export async function getOrgsByDomain(domain: string) { + return orgService.listOrganizations( + { + queries: [ + { + query: { + case: "domainQuery", + value: { domain, method: TextQueryMethod.EQUALS }, + }, + }, + ], + }, + {}, + ); } export async function startIdentityProviderFlow({ diff --git a/packages/zitadel-client/src/v3alpha.ts b/packages/zitadel-client/src/v3alpha.ts index b55626ada23..f403ad37a90 100644 --- a/packages/zitadel-client/src/v3alpha.ts +++ b/packages/zitadel-client/src/v3alpha.ts @@ -1,6 +1,6 @@ -import { UserSchemaService } from "@zitadel/proto/zitadel/user/schema/v3alpha/user_schema_service_pb"; -import { UserService } from "@zitadel/proto/zitadel/user/v3alpha/user_service_pb"; +import { ZITADELUsers } from "@zitadel/proto/zitadel/resources/user/v3alpha/user_service_connect"; +import { ZITADELUserSchemas } from "@zitadel/proto/zitadel/resources/userschema/v3alpha/user_schema_service_connect"; import { createClientFor } from "./helpers"; -export const createUserSchemaServiceClient = createClientFor(UserSchemaService); -export const createUserServiceClient = createClientFor(UserService); +export const createUserSchemaServiceClient = createClientFor(ZITADELUserSchemas); +export const createUserServiceClient = createClientFor(ZITADELUsers);