mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-12 09:54:00 +00:00
describe discovery
This commit is contained in:
@@ -58,6 +58,7 @@ Requests to the APIs made:
|
|||||||
- `startIdentityProviderFlow`
|
- `startIdentityProviderFlow`
|
||||||
- `listUsers(org?)`
|
- `listUsers(org?)`
|
||||||
- `listAuthenticationMethodTypes`
|
- `listAuthenticationMethodTypes`
|
||||||
|
- `getOrgsByDomain`
|
||||||
|
|
||||||
After a loginname is entered, a `listUsers` request is made using the loginName query to identify already registered users.
|
After a loginname is entered, a `listUsers` request is made using the loginName query to identify already registered users.
|
||||||
|
|
||||||
@@ -70,7 +71,8 @@ If password is the next step, we check `loginSettings.passkeysType` for Passkeys
|
|||||||
If no user is found, we check whether registering is allowed using `loginSettings.allowRegister`.
|
If no user is found, we check whether registering is allowed using `loginSettings.allowRegister`.
|
||||||
If `loginSettings?.allowUsernamePassword` is not allowed we continue to check for available IDPs. If a single IDP is available, we directly redirect the user to signup.
|
If `loginSettings?.allowUsernamePassword` is not allowed we continue to check for available IDPs. If a single IDP is available, we directly redirect the user to signup.
|
||||||
|
|
||||||
If no single IDP is set, we check for `loginSettings.allowUsernamePassword` and redirect the user to /register page.
|
If no single IDP is set, we check for `loginSettings.allowUsernamePassword` and if no organization is set as context, we check whether we can discover a organization from the loginname of the user (using: `getOrgsByDomain`). Then if an organization is found, we check whether domainDiscovery is allowed on it and redirect the user to /register page including the discovered domain or without.
|
||||||
|
|
||||||
If no previous condition is met we throw an error stating the user was not found.
|
If no previous condition is met we throw an error stating the user was not found.
|
||||||
|
|
||||||
If the outcome after this order produces a no authentication methods found, or user not found, we check whether `loginSettings?.ignoreUnknownUsernames` is set to `true` as in this case we redirect to the /password page regardless (to not leak information about a registered user).
|
If the outcome after this order produces a no authentication methods found, or user not found, we check whether `loginSettings?.ignoreUnknownUsernames` is set to `true` as in this case we redirect to the /password page regardless (to not leak information about a registered user).
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { idpTypeToSlug } from "../idp";
|
|||||||
import {
|
import {
|
||||||
getActiveIdentityProviders,
|
getActiveIdentityProviders,
|
||||||
getLoginSettings,
|
getLoginSettings,
|
||||||
|
getOrgsByDomain,
|
||||||
listAuthenticationMethodTypes,
|
listAuthenticationMethodTypes,
|
||||||
listUsers,
|
listUsers,
|
||||||
startIdentityProviderFlow,
|
startIdentityProviderFlow,
|
||||||
@@ -20,6 +21,8 @@ export type SendLoginnameCommand = {
|
|||||||
organization?: string;
|
organization?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ORG_SUFFIX_REGEX = /(?<=@)(.+)/;
|
||||||
|
|
||||||
export async function sendLoginname(command: SendLoginnameCommand) {
|
export async function sendLoginname(command: SendLoginnameCommand) {
|
||||||
const users = await listUsers({
|
const users = await listUsers({
|
||||||
loginName: command.loginName,
|
loginName: command.loginName,
|
||||||
@@ -181,9 +184,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check if allowDomainDiscovery has to be allowed too, to redirect to the register page
|
|
||||||
// user not found, check if register is enabled on organization
|
// user not found, check if register is enabled on organization
|
||||||
|
|
||||||
if (loginSettings?.allowRegister && !loginSettings?.allowUsernamePassword) {
|
if (loginSettings?.allowRegister && !loginSettings?.allowUsernamePassword) {
|
||||||
// TODO: do we need to handle login hints for IDPs here?
|
// TODO: do we need to handle login hints for IDPs here?
|
||||||
await redirectUserToSingleIDPIfAvailable();
|
await redirectUserToSingleIDPIfAvailable();
|
||||||
@@ -193,10 +194,31 @@ export async function sendLoginname(command: SendLoginnameCommand) {
|
|||||||
loginSettings?.allowRegister &&
|
loginSettings?.allowRegister &&
|
||||||
loginSettings?.allowUsernamePassword
|
loginSettings?.allowUsernamePassword
|
||||||
) {
|
) {
|
||||||
|
let orgToRegisterOn: string | undefined = command.organization;
|
||||||
|
|
||||||
|
if (
|
||||||
|
!orgToRegisterOn &&
|
||||||
|
command.loginName &&
|
||||||
|
ORG_SUFFIX_REGEX.test(command.loginName)
|
||||||
|
) {
|
||||||
|
const matched = ORG_SUFFIX_REGEX.exec(command.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 = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
|
|
||||||
if (command.organization) {
|
if (orgToRegisterOn) {
|
||||||
params.set("organization", command.organization);
|
params.set("organization", orgToRegisterOn);
|
||||||
}
|
}
|
||||||
if (command.authRequestId) {
|
if (command.authRequestId) {
|
||||||
params.set("authRequestId", command.authRequestId);
|
params.set("authRequestId", command.authRequestId);
|
||||||
|
|||||||
Reference in New Issue
Block a user