Merge branch 'main' into saml-2

This commit is contained in:
Max Peintner
2025-02-14 13:41:16 +01:00
72 changed files with 775 additions and 628 deletions

View File

@@ -10,10 +10,18 @@ declare namespace NodeJS {
SYSTEM_USER_PRIVATE_KEY: string; // The fallback service user private key
/**
* Self hosting: The instance url
* Self hosting: The Zitadel API url
*/
ZITADEL_API_URL: string;
/**
* Takes effect only if ZITADEL_API_URL is not empty.
* This is only relevant if Zitadels runtime has the ZITADEL_INSTANCEHOSTHEADERS config changed.
* The default is x-zitadel-instance-host.
* Most users don't need to set this variable.
*/
ZITADEL_INSTANCE_HOST_HEADER: string;
/**
* Self hosting: The service user id
*/

View File

@@ -34,27 +34,39 @@ const secureHeaders = [
},
];
const imageRemotePatterns = [
{
protocol: "http",
hostname: "localhost",
port: "8080",
pathname: "/**",
},
{
protocol: "https",
hostname: "*.zitadel.*",
port: "",
pathname: "/**",
},
];
if (process.env.ZITADEL_API_URL) {
imageRemotePatterns.push({
protocol: "https",
hostname: process.env.ZITADEL_API_URL?.replace("https://", "") || "",
port: "",
pathname: "/**",
});
}
const nextConfig = {
basePath: process.env.NEXT_PUBLIC_BASE_PATH,
output: process.env.NEXT_OUTPUT_MODE || undefined,
reactStrictMode: true, // Recommended for the `pages` directory, default in `app`.
experimental: {
dynamicIO: true,
},
images: {
remotePatterns: [
{
protocol: "https",
hostname: process.env.ZITADEL_API_URL?.replace("https://", "") || "",
port: "",
pathname: "/**",
},
{
protocol: "http",
hostname: "localhost",
port: "8080",
pathname: "/**",
},
],
remotePatterns: imageRemotePatterns,
},
async headers() {
return [

View File

@@ -23,6 +23,7 @@
"lint:fix": "prettier --write .",
"lint-staged": "lint-staged",
"build": "next build",
"build:standalone": "NEXT_OUTPUT_MODE=standalone pnpm build",
"prestart": "pnpm build",
"start": "next start",
"start:built": "next start",
@@ -62,7 +63,7 @@
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.0.1",
"@types/ms": "0.7.34",
"@types/node": "22.9.0",
"@types/node": "^20.17.17",
"@types/react": "19.0.2",
"@types/react-dom": "19.0.2",
"@types/tinycolor2": "1.4.3",

View File

@@ -13,19 +13,13 @@ import { getLocale, getTranslations } from "next-intl/server";
import { headers } from "next/headers";
import Link from "next/link";
async function loadSessions({
serviceUrl,
serviceRegion,
}: {
serviceUrl: string;
serviceRegion: string;
}) {
async function loadSessions({ serviceUrl }: { serviceUrl: string }) {
const ids: (string | undefined)[] = await getAllSessionCookieIds();
if (ids && ids.length) {
const response = await listSessions({
serviceUrl,
serviceRegion,
ids: ids.filter((id) => !!id) as string[],
});
return response?.sessions ?? [];
@@ -46,24 +40,23 @@ export default async function Page(props: {
const organization = searchParams?.organization;
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
let defaultOrganization;
if (!organization) {
const org: Organization | null = await getDefaultOrg({
serviceUrl,
serviceRegion,
});
if (org) {
defaultOrganization = org.id;
}
}
let sessions = await loadSessions({ serviceUrl, serviceRegion });
let sessions = await loadSessions({ serviceUrl });
const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization: organization ?? defaultOrganization,
});

View File

@@ -30,7 +30,7 @@ export default async function Page(props: {
const { loginName, requestId, organization, sessionId } = searchParams;
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const sessionWithData = sessionId
? await loadSessionById(serviceUrl, sessionId, organization)
@@ -38,7 +38,7 @@ export default async function Page(props: {
async function getAuthMethodsAndUser(
serviceUrl: string,
serviceRegion: string,
session?: Session,
) {
const userId = session?.factors?.user?.id;
@@ -49,10 +49,10 @@ export default async function Page(props: {
return listAuthenticationMethodTypes({
serviceUrl,
serviceRegion,
userId,
}).then((methods) => {
return getUserByID({ serviceUrl, serviceRegion, userId }).then((user) => {
return getUserByID({ serviceUrl, userId }).then((user) => {
const humanUser =
user.user?.type.case === "human" ? user.user?.type.value : undefined;
@@ -74,13 +74,13 @@ export default async function Page(props: {
) {
return loadMostRecentSession({
serviceUrl,
serviceRegion,
sessionParams: {
loginName,
organization,
},
}).then((session) => {
return getAuthMethodsAndUser(serviceUrl, serviceRegion, session);
return getAuthMethodsAndUser(serviceUrl, session);
});
}
@@ -92,13 +92,13 @@ export default async function Page(props: {
const recent = await getSessionCookieById({ sessionId, organization });
return getSession({
serviceUrl,
serviceRegion,
sessionId: recent.id,
sessionToken: recent.token,
}).then((sessionResponse) => {
return getAuthMethodsAndUser(
serviceUrl,
serviceRegion,
sessionResponse.session,
);
});
@@ -110,19 +110,19 @@ export default async function Page(props: {
const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization: sessionWithData.factors?.user?.organizationId,
});
const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization: sessionWithData.factors?.user?.organizationId,
});
const identityProviders = await getActiveIdentityProviders({
serviceUrl,
serviceRegion,
orgId: sessionWithData.factors?.user?.organizationId,
linking_allowed: true,
}).then((resp) => {

View File

@@ -1,19 +1,19 @@
import { Alert, AlertType } from "@/components/alert";
import { ChooseAuthenticatorToLogin } from "@/components/choose-authenticator-to-login";
import { DynamicTheme } from "@/components/dynamic-theme";
import { UserAvatar } from "@/components/user-avatar";
import { getServiceUrlFromHeaders } from "@/lib/service";
import { getBrandingSettings } from "@/lib/zitadel";
import { IdentityProviderType } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
import {
getBrandingSettings,
getLoginSettings,
getUserByID,
listAuthenticationMethodTypes,
} from "@/lib/zitadel";
import { HumanUser, User } from "@zitadel/proto/zitadel/user/v2/user_pb";
import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
import { getLocale, getTranslations } from "next-intl/server";
import { headers } from "next/headers";
// This configuration shows the given name in the respective IDP button as fallback
const PROVIDER_NAME_MAPPING: {
[provider: string]: string;
} = {
[IdentityProviderType.GOOGLE]: "Google",
[IdentityProviderType.GITHUB]: "GitHub",
[IdentityProviderType.AZURE_AD]: "Microsoft",
};
export default async function Page(props: {
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
params: Promise<{ provider: string }>;
@@ -22,22 +22,85 @@ export default async function Page(props: {
const locale = getLocale();
const t = await getTranslations({ locale, namespace: "idp" });
const { organization } = searchParams;
const { organization, userId } = searchParams;
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});
const loginSettings = await getLoginSettings({
serviceUrl,
organization,
});
let authMethods: AuthenticationMethodType[] = [];
let user: User | undefined = undefined;
let human: HumanUser | undefined = undefined;
const params = new URLSearchParams({});
if (organization) {
params.set("organization", organization);
}
if (userId) {
params.set("userId", userId);
}
if (userId) {
const userResponse = await getUserByID({
serviceUrl,
userId,
});
if (userResponse) {
user = userResponse.user;
if (user?.type.case === "human") {
human = user.type.value as HumanUser;
}
if (user?.preferredLoginName) {
params.set("loginName", user.preferredLoginName);
}
}
const authMethodsResponse = await listAuthenticationMethodTypes({
serviceUrl,
userId,
});
if (authMethodsResponse.authMethodTypes) {
authMethods = authMethodsResponse.authMethodTypes;
}
}
return (
<DynamicTheme branding={branding}>
<div className="flex flex-col items-center space-y-4">
<h1>{t("loginError.title")}</h1>
<p className="ztdl-p">{t("loginError.description")}</p>
<Alert type={AlertType.ALERT}>{t("loginError.description")}</Alert>
{userId && authMethods.length && (
<>
{user && human && (
<UserAvatar
loginName={user.preferredLoginName}
displayName={human?.profile?.displayName}
showDropdown={false}
/>
)}
<ChooseAuthenticatorToLogin
authMethods={authMethods}
loginSettings={loginSettings}
params={params}
></ChooseAuthenticatorToLogin>
</>
)}
</div>
</DynamicTheme>
);

View File

@@ -40,11 +40,11 @@ export default async function Page(props: {
const { provider } = params;
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});
@@ -54,7 +54,7 @@ export default async function Page(props: {
const intent = await retrieveIDPIntent({
serviceUrl,
serviceRegion,
id,
token,
});
@@ -79,7 +79,7 @@ export default async function Page(props: {
const idp = await getIDPByID({
serviceUrl,
serviceRegion,
id: idpInformation.idpId,
});
const options = idp?.config?.options;
@@ -100,7 +100,7 @@ export default async function Page(props: {
try {
idpLink = await addIDPLink({
serviceUrl,
serviceRegion,
idp: {
id: idpInformation.idpId,
userId: idpInformation.userId,
@@ -131,23 +131,21 @@ export default async function Page(props: {
const email = PROVIDER_MAPPING[providerType](idpInformation).email?.email;
if (options.autoLinking === AutoLinkingOption.EMAIL && email) {
foundUser = await listUsers({ serviceUrl, serviceRegion, email }).then(
(response) => {
return response.result ? response.result[0] : null;
},
);
foundUser = await listUsers({ serviceUrl, email }).then((response) => {
return response.result ? response.result[0] : null;
});
} else if (options.autoLinking === AutoLinkingOption.USERNAME) {
foundUser = await listUsers(
options.autoLinking === AutoLinkingOption.USERNAME
? { serviceUrl, serviceRegion, userName: idpInformation.userName }
: { serviceUrl, serviceRegion, email },
? { serviceUrl, userName: idpInformation.userName }
: { serviceUrl, email },
).then((response) => {
return response.result ? response.result[0] : null;
});
} else {
foundUser = await listUsers({
serviceUrl,
serviceRegion,
userName: idpInformation.userName,
email,
}).then((response) => {
@@ -160,7 +158,7 @@ export default async function Page(props: {
try {
idpLink = await addIDPLink({
serviceUrl,
serviceRegion,
idp: {
id: idpInformation.idpId,
userId: idpInformation.userId,
@@ -203,7 +201,7 @@ export default async function Page(props: {
// this just returns orgs where the suffix is set as primary domain
const orgs = await getOrgsByDomain({
serviceUrl,
serviceRegion,
domain: suffix,
});
const orgToCheckForDiscovery =
@@ -211,7 +209,7 @@ export default async function Page(props: {
const orgLoginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization: orgToCheckForDiscovery,
});
if (orgLoginSettings?.allowDomainDiscovery) {
@@ -232,7 +230,7 @@ export default async function Page(props: {
const newUser = await addHuman({
serviceUrl,
serviceRegion,
request: userData,
});

View File

@@ -16,11 +16,11 @@ export default async function Page(props: {
const organization = searchParams?.organization;
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const identityProviders = await getActiveIdentityProviders({
serviceUrl,
serviceRegion,
orgId: organization,
}).then((resp) => {
return resp.identityProviders;
@@ -28,7 +28,7 @@ export default async function Page(props: {
const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});

View File

@@ -21,10 +21,10 @@ export default async function Page(props: {
let { firstname, lastname, email, organization } = searchParams;
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
if (!organization) {
const org = await getDefaultOrg({ serviceUrl, serviceRegion });
const org = await getDefaultOrg({ serviceUrl });
if (!org) {
throw new Error("No default organization found");
}
@@ -34,19 +34,19 @@ export default async function Page(props: {
const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization,
});
const passwordComplexitySettings = await getPasswordComplexitySettings({
serviceUrl,
serviceRegion,
organization,
});
const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});

View File

@@ -19,10 +19,10 @@ export default async function Page(props: {
let { userId, organization } = searchParams;
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
if (!organization) {
const org = await getDefaultOrg({ serviceUrl, serviceRegion });
const org = await getDefaultOrg({ serviceUrl });
if (!org) {
throw new Error("No default organization found");
}
@@ -32,7 +32,7 @@ export default async function Page(props: {
const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});
@@ -41,7 +41,7 @@ export default async function Page(props: {
if (userId) {
const userResponse = await getUserByID({
serviceUrl,
serviceRegion,
userId,
});
if (userResponse) {

View File

@@ -26,13 +26,12 @@ export default async function Page(props: {
const submit: boolean = searchParams?.submit === "true";
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
let defaultOrganization;
if (!organization) {
const org: Organization | null = await getDefaultOrg({
serviceUrl,
serviceRegion,
});
if (org) {
defaultOrganization = org.id;
@@ -41,19 +40,19 @@ export default async function Page(props: {
const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization: organization ?? defaultOrganization,
});
const contextLoginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization,
});
const identityProviders = await getActiveIdentityProviders({
serviceUrl,
serviceRegion,
orgId: organization ?? defaultOrganization,
}).then((resp) => {
return resp.identityProviders;
@@ -61,7 +60,7 @@ export default async function Page(props: {
const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization: organization ?? defaultOrganization,
});

View File

@@ -25,7 +25,7 @@ export default async function Page(props: {
const { loginName, requestId, organization, sessionId } = searchParams;
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const sessionFactors = sessionId
? await loadSessionById(serviceUrl, sessionId, organization)
@@ -38,7 +38,7 @@ export default async function Page(props: {
) {
return loadMostRecentSession({
serviceUrl,
serviceRegion,
sessionParams: {
loginName,
organization,
@@ -47,7 +47,7 @@ export default async function Page(props: {
if (session && session.factors?.user?.id) {
return listAuthenticationMethodTypes({
serviceUrl,
serviceRegion,
userId: session.factors.user.id,
}).then((methods) => {
return {
@@ -67,14 +67,14 @@ export default async function Page(props: {
const recent = await getSessionCookieById({ sessionId, organization });
return getSession({
serviceUrl,
serviceRegion,
sessionId: recent.id,
sessionToken: recent.token,
}).then((response) => {
if (response?.session && response.session.factors?.user?.id) {
return listAuthenticationMethodTypes({
serviceUrl,
serviceRegion,
userId: response.session.factors.user.id,
}).then((methods) => {
return {
@@ -88,7 +88,7 @@ export default async function Page(props: {
const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});

View File

@@ -46,7 +46,7 @@ export default async function Page(props: {
searchParams;
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const sessionWithData = sessionId
? await loadSessionById(serviceUrl, sessionId, organization)
@@ -61,10 +61,10 @@ export default async function Page(props: {
return listAuthenticationMethodTypes({
serviceUrl,
serviceRegion,
userId,
}).then((methods) => {
return getUserByID({ serviceUrl, serviceRegion, userId }).then((user) => {
return getUserByID({ serviceUrl, userId }).then((user) => {
const humanUser =
user.user?.type.case === "human" ? user.user?.type.value : undefined;
@@ -86,7 +86,7 @@ export default async function Page(props: {
) {
return loadMostRecentSession({
serviceUrl,
serviceRegion,
sessionParams: {
loginName,
organization,
@@ -104,7 +104,7 @@ export default async function Page(props: {
const recent = await getSessionCookieById({ sessionId, organization });
return getSession({
serviceUrl,
serviceRegion,
sessionId: recent.id,
sessionToken: recent.token,
}).then((sessionResponse) => {
@@ -114,12 +114,12 @@ export default async function Page(props: {
const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});
const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization: sessionWithData.factors?.user?.organizationId,
});

View File

@@ -24,7 +24,7 @@ export default async function Page(props: {
const tError = await getTranslations({ locale, namespace: "error" });
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const host = _headers.get("host");
if (!host || typeof host !== "string") {
@@ -47,7 +47,7 @@ export default async function Page(props: {
? await loadSessionById(serviceUrl, sessionId, organization)
: await loadMostRecentSession({
serviceUrl,
serviceRegion,
sessionParams: { loginName, organization },
});
@@ -59,7 +59,7 @@ export default async function Page(props: {
const recent = await getSessionCookieById({ sessionId, organization });
return getSession({
serviceUrl,
serviceRegion,
sessionId: recent.id,
sessionToken: recent.token,
}).then((response) => {
@@ -72,13 +72,13 @@ export default async function Page(props: {
// email links do not come with organization, thus we need to use the session's organization
const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization: organization ?? session?.factors?.user?.organizationId,
});
const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization: organization ?? session?.factors?.user?.organizationId,
});

View File

@@ -34,22 +34,22 @@ export default async function Page(props: {
const { method } = params;
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});
const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization,
});
const session = await loadMostRecentSession({
serviceUrl,
serviceRegion,
sessionParams: {
loginName,
organization,
@@ -61,7 +61,7 @@ export default async function Page(props: {
if (method === "time-based") {
await registerTOTP({
serviceUrl,
serviceRegion,
userId: session.factors.user.id,
})
.then((resp) => {
@@ -76,7 +76,7 @@ export default async function Page(props: {
// does not work
await addOTPSMS({
serviceUrl,
serviceRegion,
userId: session.factors.user.id,
}).catch((error) => {
error = new Error("Could not add OTP via SMS");
@@ -85,7 +85,7 @@ export default async function Page(props: {
// works
await addOTPEmail({
serviceUrl,
serviceRegion,
userId: session.factors.user.id,
}).catch((error) => {
error = new Error("Could not add OTP via Email");

View File

@@ -21,13 +21,13 @@ export default async function Page(props: {
searchParams;
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const sessionFactors = sessionId
? await loadSessionById(serviceUrl, sessionId, organization)
: await loadMostRecentSession({
serviceUrl,
serviceRegion,
sessionParams: { loginName, organization },
});
@@ -39,7 +39,7 @@ export default async function Page(props: {
const recent = await getSessionCookieById({ sessionId, organization });
return getSession({
serviceUrl,
serviceRegion,
sessionId: recent.id,
sessionToken: recent.token,
}).then((response) => {
@@ -51,7 +51,7 @@ export default async function Page(props: {
const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});

View File

@@ -19,11 +19,11 @@ export default async function Page(props: {
const { loginName, prompt, organization, requestId, userId } = searchParams;
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const session = await loadMostRecentSession({
serviceUrl,
serviceRegion,
sessionParams: {
loginName,
organization,
@@ -32,7 +32,7 @@ export default async function Page(props: {
const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});

View File

@@ -16,7 +16,7 @@ export default async function Page(props: {
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
}) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const searchParams = await props.searchParams;
const locale = getLocale();
@@ -28,7 +28,7 @@ export default async function Page(props: {
// also allow no session to be found (ignoreUnkownUsername)
const sessionFactors = await loadMostRecentSession({
serviceUrl,
serviceRegion,
sessionParams: {
loginName,
organization,
@@ -37,19 +37,19 @@ export default async function Page(props: {
const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});
const passwordComplexity = await getPasswordComplexitySettings({
serviceUrl,
serviceRegion,
organization: sessionFactors?.factors?.user?.organizationId,
});
const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization: sessionFactors?.factors?.user?.organizationId,
});

View File

@@ -25,13 +25,12 @@ export default async function Page(props: {
let { loginName, organization, requestId, alt } = searchParams;
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
let defaultOrganization;
if (!organization) {
const org: Organization | null = await getDefaultOrg({
serviceUrl,
serviceRegion,
});
if (org) {
@@ -44,7 +43,7 @@ export default async function Page(props: {
try {
sessionFactors = await loadMostRecentSession({
serviceUrl,
serviceRegion,
sessionParams: {
loginName,
organization,
@@ -57,12 +56,12 @@ export default async function Page(props: {
const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization: organization ?? defaultOrganization,
});
const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization: organization ?? defaultOrganization,
});

View File

@@ -27,14 +27,14 @@ export default async function Page(props: {
searchParams;
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
// also allow no session to be found (ignoreUnkownUsername)
let session: Session | undefined;
if (loginName) {
session = await loadMostRecentSession({
serviceUrl,
serviceRegion,
sessionParams: {
loginName,
organization,
@@ -44,19 +44,19 @@ export default async function Page(props: {
const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});
const passwordComplexity = await getPasswordComplexitySettings({
serviceUrl,
serviceRegion,
organization: session?.factors?.user?.organizationId,
});
const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization,
});
@@ -65,7 +65,7 @@ export default async function Page(props: {
if (userId) {
const userResponse = await getUserByID({
serviceUrl,
serviceRegion,
userId,
});
user = userResponse.user;

View File

@@ -22,12 +22,11 @@ export default async function Page(props: {
let { firstname, lastname, email, organization, requestId } = searchParams;
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
if (!organization) {
const org: Organization | null = await getDefaultOrg({
serviceUrl,
serviceRegion,
});
if (org) {
organization = org.id;
@@ -36,24 +35,24 @@ export default async function Page(props: {
const legal = await getLegalAndSupportSettings({
serviceUrl,
serviceRegion,
organization,
});
const passwordComplexitySettings = await getPasswordComplexitySettings({
serviceUrl,
serviceRegion,
organization,
});
const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});
const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization,
});

View File

@@ -22,12 +22,11 @@ export default async function Page(props: {
let { firstname, lastname, email, organization, requestId } = searchParams;
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
if (!organization) {
const org: Organization | null = await getDefaultOrg({
serviceUrl,
serviceRegion,
});
if (org) {
organization = org.id;
@@ -38,24 +37,24 @@ export default async function Page(props: {
const legal = await getLegalAndSupportSettings({
serviceUrl,
serviceRegion,
organization,
});
const passwordComplexitySettings = await getPasswordComplexitySettings({
serviceUrl,
serviceRegion,
organization,
});
const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});
const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization,
});

View File

@@ -24,7 +24,7 @@ import { redirect } from "next/navigation";
async function loadSession(
serviceUrl: string,
serviceRegion: string,
loginName: string,
requestId?: string,
) {
@@ -33,7 +33,7 @@ async function loadSession(
if (requestId && requestId.startsWith("oidc_")) {
return createCallback({
serviceUrl,
serviceRegion,
req: create(CreateCallbackRequestSchema, {
authRequestId: requestId,
callbackKind: {
@@ -68,7 +68,7 @@ async function loadSession(
return getSession({
serviceUrl,
serviceRegion,
sessionId: recent.id,
sessionToken: recent.token,
}).then((response) => {
@@ -84,19 +84,19 @@ export default async function Page(props: { searchParams: Promise<any> }) {
const t = await getTranslations({ locale, namespace: "signedin" });
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const { loginName, requestId, organization } = searchParams;
const sessionFactors = await loadSession(
serviceUrl,
serviceRegion,
loginName,
requestId,
);
const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});
@@ -104,7 +104,7 @@ export default async function Page(props: { searchParams: Promise<any> }) {
if (!requestId) {
loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization,
});
}

View File

@@ -20,7 +20,7 @@ export default async function Page(props: {
const { loginName, requestId, sessionId, organization } = searchParams;
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const host = _headers.get("host");
if (!host || typeof host !== "string") {
@@ -29,7 +29,7 @@ export default async function Page(props: {
const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});
@@ -37,7 +37,7 @@ export default async function Page(props: {
? await loadSessionById(serviceUrl, sessionId, organization)
: await loadMostRecentSession({
serviceUrl,
serviceRegion,
sessionParams: { loginName, organization },
});
@@ -49,7 +49,7 @@ export default async function Page(props: {
const recent = await getSessionCookieById({ sessionId, organization });
return getSession({
serviceUrl,
serviceRegion,
sessionId: recent.id,
sessionToken: recent.token,
}).then((response) => {

View File

@@ -19,11 +19,11 @@ export default async function Page(props: {
const { loginName, organization, requestId, checkAfter } = searchParams;
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const sessionFactors = await loadMostRecentSession({
serviceUrl,
serviceRegion,
sessionParams: {
loginName,
organization,
@@ -32,7 +32,7 @@ export default async function Page(props: {
const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});

View File

@@ -26,7 +26,7 @@ export default async function Page(props: { searchParams: Promise<any> }) {
searchParams;
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const host = _headers.get("host");
if (!host || typeof host !== "string") {
@@ -35,7 +35,7 @@ export default async function Page(props: { searchParams: Promise<any> }) {
const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});
@@ -49,7 +49,7 @@ export default async function Page(props: { searchParams: Promise<any> }) {
if ("loginName" in searchParams) {
sessionFactors = await loadMostRecentSession({
serviceUrl,
serviceRegion,
sessionParams: {
loginName,
organization,
@@ -59,7 +59,7 @@ export default async function Page(props: { searchParams: Promise<any> }) {
if (doSend && sessionFactors?.factors?.user?.id) {
await sendEmailCode({
serviceUrl,
serviceRegion,
userId: sessionFactors?.factors?.user?.id,
urlTemplate:
`${host.includes("localhost") ? "http://" : "https://"}${host}/verify?code={{.Code}}&userId={{.UserID}}&organization={{.OrgID}}&invite=true` +
@@ -73,7 +73,7 @@ export default async function Page(props: { searchParams: Promise<any> }) {
if (doSend) {
await sendEmailCode({
serviceUrl,
serviceRegion,
userId,
urlTemplate:
`${host.includes("localhost") ? "http://" : "https://"}${host}/verify?code={{.Code}}&userId={{.UserID}}&organization={{.OrgID}}&invite=true` +
@@ -86,7 +86,7 @@ export default async function Page(props: { searchParams: Promise<any> }) {
const userResponse = await getUserByID({
serviceUrl,
serviceRegion,
userId,
});
if (userResponse) {

View File

@@ -56,16 +56,14 @@ const gotoAccounts = ({
async function loadSessions({
serviceUrl,
serviceRegion,
ids,
}: {
serviceUrl: string;
serviceRegion: string;
ids: string[];
}): Promise<Session[]> {
const response = await listSessions({
serviceUrl,
serviceRegion,
ids: ids.filter((id: string | undefined) => !!id),
});
@@ -78,7 +76,7 @@ const IDP_SCOPE_REGEX = /urn:zitadel:iam:org:idp:id:(.+)/;
export async function GET(request: NextRequest) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const searchParams = request.nextUrl.searchParams;
@@ -103,7 +101,7 @@ export async function GET(request: NextRequest) {
const ids = sessionCookies.map((s) => s.id);
let sessions: Session[] = [];
if (ids && ids.length) {
sessions = await loadSessions({ serviceUrl, serviceRegion, ids });
sessions = await loadSessions({ serviceUrl, ids });
}
if (requestId && sessionId) {
@@ -111,7 +109,6 @@ export async function GET(request: NextRequest) {
// this finishes the login process for OIDC
await loginWithOIDCandSession({
serviceUrl,
serviceRegion,
authRequest: requestId.replace("oidc_", ""),
sessionId,
sessions,
@@ -122,7 +119,6 @@ export async function GET(request: NextRequest) {
// this finishes the login process for SAML
await loginWithSAMLandSession({
serviceUrl,
serviceRegion,
samlRequest: requestId.replace("saml_", ""),
sessionId,
sessions,
@@ -134,7 +130,6 @@ export async function GET(request: NextRequest) {
if (requestId && requestId.startsWith("oidc_")) {
const { authRequest } = await getAuthRequest({
serviceUrl,
serviceRegion,
authRequestId: requestId.replace("oidc_", ""),
});
@@ -165,7 +160,7 @@ export async function GET(request: NextRequest) {
if (orgDomain) {
const orgs = await getOrgsByDomain({
serviceUrl,
serviceRegion,
domain: orgDomain,
});
if (orgs.result && orgs.result.length === 1) {
@@ -182,7 +177,7 @@ export async function GET(request: NextRequest) {
const identityProviders = await getActiveIdentityProviders({
serviceUrl,
serviceRegion,
orgId: organization ? organization : undefined,
}).then((resp) => {
return resp.identityProviders;
@@ -208,7 +203,7 @@ export async function GET(request: NextRequest) {
return startIdentityProviderFlow({
serviceUrl,
serviceRegion,
idpId,
urls: {
successUrl:
@@ -305,7 +300,7 @@ export async function GET(request: NextRequest) {
**/
const selectedSession = await findValidSession({
serviceUrl,
serviceRegion,
sessions,
authRequest,
});
@@ -335,7 +330,7 @@ export async function GET(request: NextRequest) {
const { callbackUrl } = await createCallback({
serviceUrl,
serviceRegion,
req: create(CreateCallbackRequestSchema, {
authRequestId: requestId.replace("oidc_", ""),
callbackKind: {
@@ -349,7 +344,6 @@ export async function GET(request: NextRequest) {
// check for loginHint, userId hint and valid sessions
let selectedSession = await findValidSession({
serviceUrl,
serviceRegion,
sessions,
authRequest,
});
@@ -384,7 +378,7 @@ export async function GET(request: NextRequest) {
try {
const { callbackUrl } = await createCallback({
serviceUrl,
serviceRegion,
req: create(CreateCallbackRequestSchema, {
authRequestId: requestId.replace("oidc_", ""),
callbackKind: {
@@ -426,7 +420,8 @@ export async function GET(request: NextRequest) {
}
if (organization) {
loginNameUrl.searchParams.set("organization", organization);
loginNameUrl.searchParams.append("organization", organization);
// loginNameUrl.searchParams.set("organization", organization);
}
return NextResponse.redirect(loginNameUrl);
@@ -435,11 +430,8 @@ export async function GET(request: NextRequest) {
// handle saml request
const { samlRequest } = await getSAMLRequest({
serviceUrl,
serviceRegion,
samlRequestId: requestId.replace("saml_", ""),
});
samlRequest?.
} else {
return NextResponse.json(
{ error: "No authRequest nor samlRequest provided" },

View File

@@ -0,0 +1,38 @@
import {
LoginSettings,
PasskeysType,
} from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
import { useTranslations } from "next-intl";
import { PASSKEYS, PASSWORD } from "./auth-methods";
type Props = {
authMethods: AuthenticationMethodType[];
params: URLSearchParams;
loginSettings: LoginSettings | undefined;
};
export function ChooseAuthenticatorToLogin({
authMethods,
params,
loginSettings,
}: Props) {
const t = useTranslations("idp");
return (
<>
{authMethods.includes(AuthenticationMethodType.PASSWORD) &&
loginSettings?.allowUsernamePassword && (
<div className="ztdl-p">Choose an alternative method to login </div>
)}
<div className="grid grid-cols-1 gap-5 w-full pt-4">
{authMethods.includes(AuthenticationMethodType.PASSWORD) &&
loginSettings?.allowUsernamePassword &&
PASSWORD(false, "/password?" + params)}
{authMethods.includes(AuthenticationMethodType.PASSKEY) &&
loginSettings?.passkeysType == PasskeysType.ALLOWED &&
PASSKEYS(false, "/passkey?" + params)}
</div>
</>
);
}

View File

@@ -1,37 +1,14 @@
import { newSystemToken } from "@zitadel/client/node";
export async function systemAPIToken({
serviceRegion,
}: {
serviceRegion: string;
}) {
const prefix = serviceRegion.toUpperCase();
export async function systemAPIToken() {
const token = {
audience: process.env[prefix + "_AUDIENCE"],
userID: process.env[prefix + "_SYSTEM_USER_ID"],
token: Buffer.from(
process.env[prefix.toUpperCase() + "_SYSTEM_USER_PRIVATE_KEY"] as string,
"base64",
).toString("utf-8"),
audience: process.env.AUDIENCE,
userID: process.env.SYSTEM_USER_ID,
token: Buffer.from(process.env.SYSTEM_USER_PRIVATE_KEY, "base64").toString(
"utf-8",
),
};
if (!token.audience || !token.userID || !token.token) {
const fallbackToken = {
audience: process.env.AUDIENCE,
userID: process.env.SYSTEM_USER_ID,
token: Buffer.from(
process.env.SYSTEM_USER_PRIVATE_KEY,
"base64",
).toString("utf-8"),
};
return newSystemToken({
audience: fallbackToken.audience,
subject: fallbackToken.userID,
key: fallbackToken.token,
});
}
return newSystemToken({
audience: token.audience,
subject: token.userID,

View File

@@ -12,7 +12,6 @@ import { isSessionValid } from "./session";
type LoginWithOIDCandSession = {
serviceUrl: string;
serviceRegion: string;
authRequest: string;
sessionId: string;
sessions: Session[];
@@ -21,7 +20,6 @@ type LoginWithOIDCandSession = {
};
export async function loginWithOIDCandSession({
serviceUrl,
serviceRegion,
authRequest,
sessionId,
sessions,
@@ -39,7 +37,6 @@ export async function loginWithOIDCandSession({
const isValid = await isSessionValid({
serviceUrl,
serviceRegion,
session: selectedSession,
});
@@ -76,7 +73,6 @@ export async function loginWithOIDCandSession({
try {
const { callbackUrl } = await createCallback({
serviceUrl,
serviceRegion,
req: create(CreateCallbackRequestSchema, {
authRequestId: authRequest,
callbackKind: {
@@ -104,7 +100,6 @@ export async function loginWithOIDCandSession({
) {
const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization: selectedSession.factors?.user?.organizationId,
});

View File

@@ -9,7 +9,6 @@ import { isSessionValid } from "./session";
type LoginWithSAMLandSession = {
serviceUrl: string;
serviceRegion: string;
samlRequest: string;
sessionId: string;
sessions: Session[];
@@ -19,7 +18,6 @@ type LoginWithSAMLandSession = {
export async function loginWithSAMLandSession({
serviceUrl,
serviceRegion,
samlRequest,
sessionId,
sessions,
@@ -37,7 +35,6 @@ export async function loginWithSAMLandSession({
const isValid = await isSessionValid({
serviceUrl,
serviceRegion,
session: selectedSession,
});
@@ -74,7 +71,6 @@ export async function loginWithSAMLandSession({
try {
const { url } = await createResponse({
serviceUrl,
serviceRegion,
req: create(CreateResponseRequestSchema, {
samlRequestId: samlRequest,
responseKind: {
@@ -102,7 +98,6 @@ export async function loginWithSAMLandSession({
) {
const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization: selectedSession.factors?.user?.organizationId,
});

View File

@@ -26,13 +26,13 @@ export async function setMyPassword({
password: string;
}) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const sessionCookie = await getSessionCookieById({ sessionId });
const { session } = await getSession({
serviceUrl,
serviceRegion,
sessionId: sessionCookie.id,
sessionToken: sessionCookie.token,
});

View File

@@ -53,11 +53,11 @@ export async function createSessionAndUpdateCookie(
lifetime?: Duration,
): Promise<Session> {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const createdSession = await createSessionFromChecks({
serviceUrl,
serviceRegion,
checks,
challenges,
lifetime,
@@ -66,7 +66,7 @@ export async function createSessionAndUpdateCookie(
if (createdSession) {
return getSession({
serviceUrl,
serviceRegion,
sessionId: createdSession.sessionId,
sessionToken: createdSession.sessionToken,
}).then((response) => {
@@ -117,11 +117,11 @@ export async function createSessionForIdpAndUpdateCookie(
lifetime?: Duration,
): Promise<Session> {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const createdSession = await createSessionForUserIdAndIdpIntent({
serviceUrl,
serviceRegion,
userId,
idpIntent,
lifetime,
@@ -142,7 +142,7 @@ export async function createSessionForIdpAndUpdateCookie(
const { session } = await getSession({
serviceUrl,
serviceRegion,
sessionId: createdSession.sessionId,
sessionToken: createdSession.sessionToken,
});
@@ -190,11 +190,11 @@ export async function setSessionAndUpdateCookie(
lifetime?: Duration,
) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
return setSession({
serviceUrl,
serviceRegion,
sessionId: recentCookie.id,
sessionToken: recentCookie.token,
challenges,
@@ -222,7 +222,7 @@ export async function setSessionAndUpdateCookie(
return getSession({
serviceUrl,
serviceRegion,
sessionId: sessionCookie.id,
sessionToken: sessionCookie.token,
}).then((response) => {

View File

@@ -19,7 +19,7 @@ export type StartIDPFlowCommand = {
export async function startIDPFlow(command: StartIDPFlowCommand) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const host = _headers.get("host");
if (!host) {
@@ -28,7 +28,7 @@ export async function startIDPFlow(command: StartIDPFlowCommand) {
return startIdentityProviderFlow({
serviceUrl,
serviceRegion,
idpId: command.idpId,
urls: {
successUrl: `${host.includes("localhost") ? "http://" : "https://"}${host}${command.successUrl}`,
@@ -61,7 +61,7 @@ export async function createNewSessionFromIdpIntent(
command: CreateNewSessionCommand,
) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const host = _headers.get("host");
if (!host) {
@@ -74,7 +74,7 @@ export async function createNewSessionFromIdpIntent(
const userResponse = await getUserByID({
serviceUrl,
serviceRegion,
userId: command.userId,
});
@@ -84,7 +84,7 @@ export async function createNewSessionFromIdpIntent(
const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization: userResponse.user.details?.resourceOwner,
});

View File

@@ -22,7 +22,7 @@ export type RegisterUserResponse = {
export async function inviteUser(command: InviteUserCommand) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const host = _headers.get("host");
if (!host) {
@@ -31,7 +31,7 @@ export async function inviteUser(command: InviteUserCommand) {
const human = await addHumanUser({
serviceUrl,
serviceRegion,
email: command.email,
firstName: command.firstName,
lastName: command.lastName,
@@ -45,7 +45,7 @@ export async function inviteUser(command: InviteUserCommand) {
const codeResponse = await createInviteCode({
serviceUrl,
serviceRegion,
urlTemplate: `${host.includes("localhost") ? "http://" : "https://"}${host}/verify?code={{.Code}}&userId={{.UserID}}&organization={{.OrgID}}&invite=true`,
userId: human.userId,
});

View File

@@ -34,7 +34,7 @@ const ORG_SUFFIX_REGEX = /(?<=@)(.+)/;
export async function sendLoginname(command: SendLoginnameCommand) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const host = _headers.get("host");
if (!host) {
@@ -43,7 +43,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
const loginSettingsByContext = await getLoginSettings({
serviceUrl,
serviceRegion,
organization: command.organization,
});
@@ -53,7 +53,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
let searchUsersRequest: SearchUsersCommand = {
serviceUrl,
serviceRegion,
searchValue: command.loginName,
organizationId: command.organization,
loginSettings: loginSettingsByContext,
@@ -75,7 +75,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
const redirectUserToSingleIDPIfAvailable = async () => {
const identityProviders = await getActiveIdentityProviders({
serviceUrl,
serviceRegion,
orgId: command.organization,
}).then((resp) => {
return resp.identityProviders;
@@ -83,7 +83,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
if (identityProviders.length === 1) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const host = _headers.get("host");
if (!host) {
@@ -106,7 +106,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
const resp = await startIdentityProviderFlow({
serviceUrl,
serviceRegion,
idpId: identityProviders[0].id,
urls: {
successUrl:
@@ -127,7 +127,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
const redirectUserToIDP = async (userId: string) => {
const identityProviders = await listIDPLinks({
serviceUrl,
serviceRegion,
userId,
}).then((resp) => {
return resp.result;
@@ -135,7 +135,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
if (identityProviders.length === 1) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const host = _headers.get("host");
if (!host) {
@@ -146,7 +146,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
const idp = await getIDPByID({
serviceUrl,
serviceRegion,
id: identityProviderId,
});
@@ -159,7 +159,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
const identityProviderType = idpTypeToIdentityProviderType(idpType);
const provider = idpTypeToSlug(identityProviderType);
const params = new URLSearchParams();
const params = new URLSearchParams({ userId });
if (command.requestId) {
params.set("requestId", command.requestId);
@@ -171,7 +171,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
const resp = await startIdentityProviderFlow({
serviceUrl,
serviceRegion,
idpId: idp.id,
urls: {
successUrl:
@@ -197,7 +197,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
const userLoginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization: user.details?.resourceOwner,
});
@@ -256,7 +256,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
const methods = await listAuthenticationMethodTypes({
serviceUrl,
serviceRegion,
userId: session.factors?.user?.id,
});
@@ -415,7 +415,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
// this just returns orgs where the suffix is set as primary domain
const orgs = await getOrgsByDomain({
serviceUrl,
serviceRegion,
domain: suffix,
});
const orgToCheckForDiscovery =
@@ -423,7 +423,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
const orgLoginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization: orgToCheckForDiscovery,
});
if (orgLoginSettings?.allowDomainDiscovery) {

View File

@@ -27,7 +27,7 @@ export type SetOTPCommand = {
export async function setOTP(command: SetOTPCommand) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const recentSession = command.sessionId
? await getSessionCookieById({ sessionId: command.sessionId }).catch(
@@ -64,7 +64,7 @@ export async function setOTP(command: SetOTPCommand) {
const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization: command.organization,
});

View File

@@ -43,7 +43,7 @@ export async function registerPasskeyLink(
const { sessionId } = command;
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const host = _headers.get("host");
if (!host) {
@@ -53,7 +53,7 @@ export async function registerPasskeyLink(
const sessionCookie = await getSessionCookieById({ sessionId });
const session = await getSession({
serviceUrl,
serviceRegion,
sessionId: sessionCookie.id,
sessionToken: sessionCookie.token,
});
@@ -74,7 +74,7 @@ export async function registerPasskeyLink(
// use session token to add the passkey
const registerLink = await createPasskeyRegistrationLink({
serviceUrl,
serviceRegion,
userId,
});
@@ -84,7 +84,7 @@ export async function registerPasskeyLink(
return registerPasskey({
serviceUrl,
serviceRegion,
userId,
code: registerLink.code,
domain: hostname,
@@ -93,7 +93,7 @@ export async function registerPasskeyLink(
export async function verifyPasskeyRegistration(command: VerifyPasskeyCommand) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
// if no name is provided, try to generate one from the user agent
let passkeyName = command.passkeyName;
@@ -112,7 +112,7 @@ export async function verifyPasskeyRegistration(command: VerifyPasskeyCommand) {
});
const session = await getSession({
serviceUrl,
serviceRegion,
sessionId: sessionCookie.id,
sessionToken: sessionCookie.token,
});
@@ -124,7 +124,7 @@ export async function verifyPasskeyRegistration(command: VerifyPasskeyCommand) {
return zitadelVerifyPasskeyRegistration({
serviceUrl,
serviceRegion,
request: create(VerifyPasskeyRegistrationRequestSchema, {
passkeyId: command.passkeyId,
publicKeyCredential: command.publicKeyCredential,
@@ -158,11 +158,11 @@ export async function sendPasskey(command: SendPasskeyCommand) {
}
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization,
});
@@ -186,7 +186,7 @@ export async function sendPasskey(command: SendPasskeyCommand) {
const userResponse = await getUserByID({
serviceUrl,
serviceRegion,
userId: session?.factors?.user?.id,
});

View File

@@ -47,7 +47,7 @@ type ResetPasswordCommand = {
export async function resetPassword(command: ResetPasswordCommand) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const host = _headers.get("host");
if (!host || typeof host !== "string") {
@@ -56,7 +56,7 @@ export async function resetPassword(command: ResetPasswordCommand) {
const users = await listUsers({
serviceUrl,
serviceRegion,
loginName: command.loginName,
organizationId: command.organization,
});
@@ -72,7 +72,7 @@ export async function resetPassword(command: ResetPasswordCommand) {
return passwordReset({
serviceUrl,
serviceRegion,
userId,
urlTemplate:
`${host.includes("localhost") ? "http://" : "https://"}${host}/password/set?code={{.Code}}&userId={{.UserID}}&organization={{.OrgID}}` +
@@ -89,7 +89,7 @@ export type UpdateSessionCommand = {
export async function sendPassword(command: UpdateSessionCommand) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
let sessionCookie = await getSessionCookieByLoginName({
loginName: command.loginName,
@@ -105,7 +105,7 @@ export async function sendPassword(command: UpdateSessionCommand) {
if (!sessionCookie) {
const users = await listUsers({
serviceUrl,
serviceRegion,
loginName: command.loginName,
organizationId: command.organization,
});
@@ -120,7 +120,7 @@ export async function sendPassword(command: UpdateSessionCommand) {
loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization: command.organization,
});
@@ -135,7 +135,7 @@ export async function sendPassword(command: UpdateSessionCommand) {
if ("failedAttempts" in error && error.failedAttempts) {
const lockoutSettings = await getLockoutSettings({
serviceUrl,
serviceRegion,
orgId: command.organization,
});
@@ -167,7 +167,7 @@ export async function sendPassword(command: UpdateSessionCommand) {
if ("failedAttempts" in error && error.failedAttempts) {
const lockoutSettings = await getLockoutSettings({
serviceUrl,
serviceRegion,
orgId: command.organization,
});
@@ -189,7 +189,7 @@ export async function sendPassword(command: UpdateSessionCommand) {
const userResponse = await getUserByID({
serviceUrl,
serviceRegion,
userId: session?.factors?.user?.id,
});
@@ -203,7 +203,7 @@ export async function sendPassword(command: UpdateSessionCommand) {
if (!loginSettings) {
loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization:
command.organization ?? session.factors?.user?.organizationId,
});
@@ -217,7 +217,7 @@ export async function sendPassword(command: UpdateSessionCommand) {
const expirySettings = await getPasswordExpirySettings({
serviceUrl,
serviceRegion,
orgId: command.organization ?? session.factors?.user?.organizationId,
});
@@ -256,7 +256,7 @@ export async function sendPassword(command: UpdateSessionCommand) {
if (command.checks && command.checks.password && session.factors?.user?.id) {
const response = await listAuthenticationMethodTypes({
serviceUrl,
serviceRegion,
userId: session.factors.user.id,
});
if (response.authMethodTypes && response.authMethodTypes.length) {
@@ -311,12 +311,12 @@ export async function changePassword(command: {
password: string;
}) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
// check for init state
const { user } = await getUserByID({
serviceUrl,
serviceRegion,
userId: command.userId,
});
@@ -327,7 +327,7 @@ export async function changePassword(command: {
return setUserPassword({
serviceUrl,
serviceRegion,
userId,
password: command.password,
user,
@@ -345,13 +345,13 @@ export async function checkSessionAndSetPassword({
password,
}: CheckSessionAndSetPasswordCommand) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const sessionCookie = await getSessionCookieById({ sessionId });
const { session } = await getSession({
serviceUrl,
serviceRegion,
sessionId: sessionCookie.id,
sessionToken: sessionCookie.token,
});
@@ -370,7 +370,7 @@ export async function checkSessionAndSetPassword({
// check if the user has no password set in order to set a password
const authmethods = await listAuthenticationMethodTypes({
serviceUrl,
serviceRegion,
userId: session.factors.user.id,
});
@@ -391,7 +391,7 @@ export async function checkSessionAndSetPassword({
const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization: session.factors.user.organizationId,
});
@@ -401,16 +401,14 @@ export async function checkSessionAndSetPassword({
// if the user has no MFA but MFA is enforced, we can set a password otherwise we use the token of the user
if (forceMfa && hasNoMFAMethods) {
return setPassword({ serviceUrl, serviceRegion, payload }).catch(
(error) => {
// throw error if failed precondition (ex. User is not yet initialized)
if (error.code === 9 && error.message) {
return { error: "Failed precondition" };
} else {
throw error;
}
},
);
return setPassword({ serviceUrl, payload }).catch((error) => {
// throw error if failed precondition (ex. User is not yet initialized)
if (error.code === 9 && error.message) {
return { error: "Failed precondition" };
} else {
throw error;
}
});
} else {
const transport = async (serviceUrl: string, token: string) => {
return createServerTransport(token, {

View File

@@ -29,7 +29,7 @@ export type RegisterUserResponse = {
};
export async function registerUser(command: RegisterUserCommand) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const host = _headers.get("host");
if (!host || typeof host !== "string") {
@@ -38,7 +38,7 @@ export async function registerUser(command: RegisterUserCommand) {
const addResponse = await addHumanUser({
serviceUrl,
serviceRegion,
email: command.email,
firstName: command.firstName,
lastName: command.lastName,
@@ -52,7 +52,7 @@ export async function registerUser(command: RegisterUserCommand) {
const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization: command.organization,
});
@@ -94,7 +94,7 @@ export async function registerUser(command: RegisterUserCommand) {
} else {
const userResponse = await getUserByID({
serviceUrl,
serviceRegion,
userId: session?.factors?.user?.id,
});

View File

@@ -25,11 +25,11 @@ export async function continueWithSession({
...session
}: Session & { requestId?: string }) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization: session.factors?.user?.organizationId,
});
@@ -83,7 +83,7 @@ export async function updateSession(options: UpdateSessionCommand) {
}
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const host = _headers.get("host");
if (!host) {
@@ -103,7 +103,7 @@ export async function updateSession(options: UpdateSessionCommand) {
const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization,
});
@@ -130,7 +130,7 @@ export async function updateSession(options: UpdateSessionCommand) {
if (checks && checks.password && session.factors?.user?.id) {
const response = await listAuthenticationMethodTypes({
serviceUrl,
serviceRegion,
userId: session.factors.user.id,
});
if (response.authMethodTypes && response.authMethodTypes.length) {
@@ -152,7 +152,7 @@ type ClearSessionOptions = {
export async function clearSession(options: ClearSessionOptions) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const { sessionId } = options;
@@ -160,7 +160,7 @@ export async function clearSession(options: ClearSessionOptions) {
const deletedSession = await deleteSession({
serviceUrl,
serviceRegion,
sessionId: session.id,
sessionToken: session.token,
});
@@ -176,13 +176,13 @@ type CleanupSessionCommand = {
export async function cleanupSession({ sessionId }: CleanupSessionCommand) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const sessionCookie = await getSessionCookieById({ sessionId });
const deleteResponse = await deleteSession({
serviceUrl,
serviceRegion,
sessionId: sessionCookie.id,
sessionToken: sessionCookie.token,
});

View File

@@ -21,7 +21,7 @@ type VerifyU2FCommand = {
export async function addU2F(command: RegisterU2FCommand) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const host = _headers.get("host");
if (!host || typeof host !== "string") {
@@ -38,7 +38,7 @@ export async function addU2F(command: RegisterU2FCommand) {
const session = await getSession({
serviceUrl,
serviceRegion,
sessionId: sessionCookie.id,
sessionToken: sessionCookie.token,
});
@@ -55,12 +55,12 @@ export async function addU2F(command: RegisterU2FCommand) {
return { error: "Could not get session" };
}
return registerU2F({ serviceUrl, serviceRegion, userId, domain: hostname });
return registerU2F({ serviceUrl, userId, domain: hostname });
}
export async function verifyU2F(command: VerifyU2FCommand) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const host = _headers.get("host");
if (!host || typeof host !== "string") {
@@ -83,7 +83,7 @@ export async function verifyU2F(command: VerifyU2FCommand) {
const session = await getSession({
serviceUrl,
serviceRegion,
sessionId: sessionCookie.id,
sessionToken: sessionCookie.token,
});
@@ -101,5 +101,5 @@ export async function verifyU2F(command: VerifyU2FCommand) {
userId,
});
return verifyU2FRegistration({ serviceUrl, serviceRegion, request });
return verifyU2FRegistration({ serviceUrl, request });
}

View File

@@ -30,11 +30,11 @@ export async function verifyTOTP(
organization?: string,
) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
return loadMostRecentSession({
serviceUrl,
serviceRegion,
sessionParams: {
loginName,
organization,
@@ -43,7 +43,7 @@ export async function verifyTOTP(
if (session?.factors?.user?.id) {
return verifyTOTPRegistration({
serviceUrl,
serviceRegion,
code,
userId: session.factors.user.id,
});
@@ -64,12 +64,12 @@ type VerifyUserByEmailCommand = {
export async function sendVerification(command: VerifyUserByEmailCommand) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const verifyResponse = command.isInvite
? await verifyInviteCode({
serviceUrl,
serviceRegion,
userId: command.userId,
verificationCode: command.code,
}).catch(() => {
@@ -77,7 +77,7 @@ export async function sendVerification(command: VerifyUserByEmailCommand) {
})
: await verifyEmail({
serviceUrl,
serviceRegion,
userId: command.userId,
verificationCode: command.code,
}).catch(() => {
@@ -109,7 +109,7 @@ export async function sendVerification(command: VerifyUserByEmailCommand) {
session = await getSession({
serviceUrl,
serviceRegion,
sessionId: sessionCookie.id,
sessionToken: sessionCookie.token,
}).then((response) => {
@@ -124,7 +124,7 @@ export async function sendVerification(command: VerifyUserByEmailCommand) {
const userResponse = await getUserByID({
serviceUrl,
serviceRegion,
userId: session?.factors?.user?.id,
});
@@ -136,7 +136,7 @@ export async function sendVerification(command: VerifyUserByEmailCommand) {
} else {
const userResponse = await getUserByID({
serviceUrl,
serviceRegion,
userId: command.userId,
});
@@ -176,13 +176,13 @@ export async function sendVerification(command: VerifyUserByEmailCommand) {
const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization: user.details?.resourceOwner,
});
const authMethodResponse = await listAuthenticationMethodTypes({
serviceUrl,
serviceRegion,
userId: user.userId,
});
@@ -253,7 +253,7 @@ type resendVerifyEmailCommand = {
export async function resendVerification(command: resendVerifyEmailCommand) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const host = _headers.get("host");
if (!host) {
@@ -261,11 +261,11 @@ export async function resendVerification(command: resendVerifyEmailCommand) {
}
return command.isInvite
? resendInviteCode({ serviceUrl, serviceRegion, userId: command.userId })
? resendInviteCode({ serviceUrl, userId: command.userId })
: resendEmailCode({
userId: command.userId,
serviceUrl,
serviceRegion,
urlTemplate:
`${host.includes("localhost") ? "http://" : "https://"}${host}/password/set?code={{.Code}}&userId={{.UserID}}&organization={{.OrgID}}` +
(command.requestId ? `&requestId=${command.requestId}` : ""),
@@ -274,7 +274,7 @@ export async function resendVerification(command: resendVerifyEmailCommand) {
type sendEmailCommand = {
serviceUrl: string;
serviceRegion: string;
userId: string;
urlTemplate: string;
};
@@ -282,7 +282,6 @@ type sendEmailCommand = {
export async function sendEmailCode(command: sendEmailCommand) {
return zitadelSendEmailCode({
serviceUrl: command.serviceUrl,
serviceRegion: command.serviceRegion,
userId: command.userId,
urlTemplate: command.urlTemplate,
});
@@ -300,7 +299,7 @@ export async function sendVerificationRedirectWithoutCheck(
command: SendVerificationRedirectWithoutCheckCommand,
) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
if (!("loginName" in command || "userId" in command)) {
return { error: "No userId, nor loginname provided" };
@@ -323,7 +322,7 @@ export async function sendVerificationRedirectWithoutCheck(
session = await getSession({
serviceUrl,
serviceRegion,
sessionId: sessionCookie.id,
sessionToken: sessionCookie.token,
}).then((response) => {
@@ -338,7 +337,7 @@ export async function sendVerificationRedirectWithoutCheck(
const userResponse = await getUserByID({
serviceUrl,
serviceRegion,
userId: session?.factors?.user?.id,
});
@@ -350,7 +349,7 @@ export async function sendVerificationRedirectWithoutCheck(
} else if ("userId" in command) {
const userResponse = await getUserByID({
serviceUrl,
serviceRegion,
userId: command.userId,
});
@@ -390,7 +389,7 @@ export async function sendVerificationRedirectWithoutCheck(
const authMethodResponse = await listAuthenticationMethodTypes({
serviceUrl,
serviceRegion,
userId: user.userId,
});
@@ -416,7 +415,7 @@ export async function sendVerificationRedirectWithoutCheck(
const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization: user.details?.resourceOwner,
});

View File

@@ -22,17 +22,16 @@ type ServiceClass =
export async function createServiceForHost<T extends ServiceClass>(
service: T,
serviceUrl: string,
serviceRegion: string,
) {
let token;
// if we are running in a multitenancy context, use the system user token
if (
process.env[serviceRegion + "_AUDIENCE"] &&
process.env[serviceRegion + "_SYSTEM_USER_ID"] &&
process.env[serviceRegion + "_SYSTEM_USER_PRIVATE_KEY"]
process.env.AUDIENCE &&
process.env.SYSTEM_USER_ID &&
process.env.SYSTEM_USER_PRIVATE_KEY
) {
token = await systemAPIToken({ serviceRegion });
token = await systemAPIToken();
} else if (process.env.ZITADEL_SERVICE_USER_TOKEN) {
token = process.env.ZITADEL_SERVICE_USER_TOKEN;
}
@@ -45,39 +44,70 @@ export async function createServiceForHost<T extends ServiceClass>(
throw new Error("No token found");
}
const instanceHost = new URL(serviceUrl).host;
const transport = createServerTransport(token, {
baseUrl: serviceUrl,
baseUrl: process.env.ZITADEL_API_URL ?? serviceUrl,
interceptors:
(process.env.ZITADEL_API_URL &&
process.env.ZITADEL_API_URL != serviceUrl) ||
process.env.ZITADEL_INSTANCE_HOST_HEADER
? [
(next) => {
return (req) => {
req.header.set(
process.env.ZITADEL_INSTANCE_HOST_HEADER ??
"x-zitadel-instance-host",
instanceHost,
);
return next(req);
};
},
]
: undefined,
});
return createClientFor<T>(service)(transport);
}
/**
* Extracts the service url and region from the headers if used in a multitenant context (host, x-zitadel-forward-host header)
* or falls back to the ZITADEL_API_URL for a self hosting deployment
* or falls back to the host header for a self hosting deployment using custom domains
* @param headers
* @returns the service url and region from the headers
* @throws if the service url could not be determined
*
*/
export function getServiceUrlFromHeaders(headers: ReadonlyHeaders): {
serviceUrl: string;
serviceRegion: string;
} {
let instanceUrl: string = process.env.ZITADEL_API_URL;
let instanceUrl;
const forwardedHost = headers.get("x-zitadel-forward-host");
// use the forwarded host if available (multitenant), otherwise fall back to the host of the deployment itself
if (forwardedHost) {
instanceUrl = forwardedHost;
instanceUrl = instanceUrl.startsWith("https://")
instanceUrl = instanceUrl.startsWith("http://")
? instanceUrl
: `https://${instanceUrl}`;
} else if (process.env.ZITADEL_API_URL) {
instanceUrl = process.env.ZITADEL_API_URL;
} else {
const host = headers.get("host");
if (host) {
const [hostname, port] = host.split(":");
if (hostname !== "localhost") {
instanceUrl = host;
instanceUrl = host.startsWith("http") ? host : `https://${host}`;
}
}
}
if (!instanceUrl) {
throw new Error("Service URL could not be determined");
}
return {
serviceUrl: instanceUrl,
serviceRegion: headers.get("x-zitadel-region") || "",
};
}

View File

@@ -12,7 +12,7 @@ import {
type LoadMostRecentSessionParams = {
serviceUrl: string;
serviceRegion: string;
sessionParams: {
loginName?: string;
organization?: string;
@@ -21,7 +21,7 @@ type LoadMostRecentSessionParams = {
export async function loadMostRecentSession({
serviceUrl,
serviceRegion,
sessionParams,
}: LoadMostRecentSessionParams): Promise<Session | undefined> {
const recent = await getMostRecentCookieWithLoginname({
@@ -31,7 +31,7 @@ export async function loadMostRecentSession({
return getSession({
serviceUrl,
serviceRegion,
sessionId: recent.id,
sessionToken: recent.token,
}).then((resp: GetSessionResponse) => resp.session);
@@ -43,11 +43,9 @@ export async function loadMostRecentSession({
**/
export async function isSessionValid({
serviceUrl,
serviceRegion,
session,
}: {
serviceUrl: string;
serviceRegion: string;
session: Session;
}): Promise<boolean> {
// session can't be checked without user
@@ -60,7 +58,6 @@ export async function isSessionValid({
const authMethodTypes = await listAuthenticationMethodTypes({
serviceUrl,
serviceRegion,
userId: session.factors.user.id,
});
@@ -110,7 +107,6 @@ export async function isSessionValid({
// only check settings if no auth methods are available, as this would require a setup
const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization: session.factors?.user?.organizationId,
});
if (loginSettings?.forceMfa || loginSettings?.forceMfaLocalOnly) {
@@ -154,12 +150,11 @@ export async function isSessionValid({
export async function findValidSession({
serviceUrl,
serviceRegion,
sessions,
authRequest,
}: {
serviceUrl: string;
serviceRegion: string;
sessions: Session[];
authRequest: AuthRequest;
}): Promise<Session | undefined> {
@@ -186,7 +181,7 @@ export async function findValidSession({
// return the first valid session according to settings
for (const session of sessionsWithHint) {
if (await isSessionValid({ serviceUrl, serviceRegion, session })) {
if (await isSessionValid({ serviceUrl, session })) {
return session;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -23,7 +23,7 @@ export async function middleware(request: NextRequest) {
const _headers = await headers();
const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
const instanceHost = `${serviceUrl}`.replace("https://", "");