Merge pull request #353 from zitadel/multiple-regions

feat(multitenancy): allow multiple regions
This commit is contained in:
Max Peintner
2025-01-30 10:26:15 +01:00
committed by GitHub
43 changed files with 725 additions and 232 deletions

View File

@@ -1,19 +1,13 @@
declare namespace NodeJS { declare namespace NodeJS {
interface ProcessEnv { interface ProcessEnv {
/** // Allow any environment variable that matches the pattern
* Multitenancy: The system api url [key: `${string}_AUDIENCE`]: string; // The system api url
*/ [key: `${string}_SYSTEM_USER_ID`]: string; // The service user id
AUDIENCE: string; [key: `${string}_SYSTEM_USER_PRIVATE_KEY`]: string; // The service user private key
/** AUDIENCE: string; // The fallback system api url
* Multitenancy: The service user id SYSTEM_USER_ID: string; // The fallback service user id
*/ SYSTEM_USER_PRIVATE_KEY: string; // The fallback service user private key
SYSTEM_USER_ID: string;
/**
* Multitenancy: The service user private key
*/
SYSTEM_USER_PRIVATE_KEY: string;
/** /**
* Self hosting: The instance url * Self hosting: The instance url

View File

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

View File

@@ -30,37 +30,41 @@ export default async function Page(props: {
const { loginName, authRequestId, organization, sessionId } = searchParams; const { loginName, authRequestId, organization, sessionId } = searchParams;
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const sessionWithData = sessionId const sessionWithData = sessionId
? await loadSessionById(serviceUrl, sessionId, organization) ? await loadSessionById(serviceUrl, sessionId, organization)
: await loadSessionByLoginname(serviceUrl, loginName, organization); : await loadSessionByLoginname(serviceUrl, loginName, organization);
async function getAuthMethodsAndUser(host: string, session?: Session) { async function getAuthMethodsAndUser(
serviceUrl: string,
serviceRegion: string,
session?: Session,
) {
const userId = session?.factors?.user?.id; const userId = session?.factors?.user?.id;
if (!userId) { if (!userId) {
throw Error("Could not get user id from session"); throw Error("Could not get user id from session");
} }
return listAuthenticationMethodTypes({ serviceUrl, userId }).then( return listAuthenticationMethodTypes({
(methods) => { serviceUrl,
return getUserByID({ serviceUrl, userId }).then((user) => { serviceRegion,
const humanUser = userId,
user.user?.type.case === "human" }).then((methods) => {
? user.user?.type.value return getUserByID({ serviceUrl, serviceRegion, userId }).then((user) => {
: undefined; const humanUser =
user.user?.type.case === "human" ? user.user?.type.value : undefined;
return { return {
factors: session?.factors, factors: session?.factors,
authMethods: methods.authMethodTypes ?? [], authMethods: methods.authMethodTypes ?? [],
phoneVerified: humanUser?.phone?.isVerified ?? false, phoneVerified: humanUser?.phone?.isVerified ?? false,
emailVerified: humanUser?.email?.isVerified ?? false, emailVerified: humanUser?.email?.isVerified ?? false,
expirationDate: session?.expirationDate, expirationDate: session?.expirationDate,
}; };
}); });
}, });
);
} }
async function loadSessionByLoginname( async function loadSessionByLoginname(
@@ -70,12 +74,13 @@ export default async function Page(props: {
) { ) {
return loadMostRecentSession({ return loadMostRecentSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionParams: { sessionParams: {
loginName, loginName,
organization, organization,
}, },
}).then((session) => { }).then((session) => {
return getAuthMethodsAndUser(serviceUrl, session); return getAuthMethodsAndUser(serviceUrl, serviceRegion, session);
}); });
} }
@@ -87,10 +92,15 @@ export default async function Page(props: {
const recent = await getSessionCookieById({ sessionId, organization }); const recent = await getSessionCookieById({ sessionId, organization });
return getSession({ return getSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionId: recent.id, sessionId: recent.id,
sessionToken: recent.token, sessionToken: recent.token,
}).then((sessionResponse) => { }).then((sessionResponse) => {
return getAuthMethodsAndUser(serviceUrl, sessionResponse.session); return getAuthMethodsAndUser(
serviceUrl,
serviceRegion,
sessionResponse.session,
);
}); });
} }
@@ -100,16 +110,19 @@ export default async function Page(props: {
const branding = await getBrandingSettings({ const branding = await getBrandingSettings({
serviceUrl, serviceUrl,
serviceRegion,
organization: sessionWithData.factors?.user?.organizationId, organization: sessionWithData.factors?.user?.organizationId,
}); });
const loginSettings = await getLoginSettings({ const loginSettings = await getLoginSettings({
serviceUrl, serviceUrl,
serviceRegion,
organization: sessionWithData.factors?.user?.organizationId, organization: sessionWithData.factors?.user?.organizationId,
}); });
const identityProviders = await getActiveIdentityProviders({ const identityProviders = await getActiveIdentityProviders({
serviceUrl, serviceUrl,
serviceRegion,
orgId: sessionWithData.factors?.user?.organizationId, orgId: sessionWithData.factors?.user?.organizationId,
linking_allowed: true, linking_allowed: true,
}).then((resp) => { }).then((resp) => {

View File

@@ -25,9 +25,13 @@ export default async function Page(props: {
const { organization } = searchParams; const { organization } = searchParams;
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const branding = await getBrandingSettings({ serviceUrl, organization }); const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});
return ( return (
<DynamicTheme branding={branding}> <DynamicTheme branding={branding}>

View File

@@ -40,9 +40,13 @@ export default async function Page(props: {
const { provider } = params; const { provider } = params;
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const branding = await getBrandingSettings({ serviceUrl, organization }); const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});
if (!provider || !id || !token) { if (!provider || !id || !token) {
return loginFailed(branding, "IDP context missing"); return loginFailed(branding, "IDP context missing");
@@ -50,6 +54,7 @@ export default async function Page(props: {
const intent = await retrieveIDPIntent({ const intent = await retrieveIDPIntent({
serviceUrl, serviceUrl,
serviceRegion,
id, id,
token, token,
}); });
@@ -72,7 +77,11 @@ export default async function Page(props: {
return loginFailed(branding, "IDP information missing"); return loginFailed(branding, "IDP information missing");
} }
const idp = await getIDPByID({ serviceUrl, id: idpInformation.idpId }); const idp = await getIDPByID({
serviceUrl,
serviceRegion,
id: idpInformation.idpId,
});
const options = idp?.config?.options; const options = idp?.config?.options;
if (!idp) { if (!idp) {
@@ -91,6 +100,7 @@ export default async function Page(props: {
try { try {
idpLink = await addIDPLink({ idpLink = await addIDPLink({
serviceUrl, serviceUrl,
serviceRegion,
idp: { idp: {
id: idpInformation.idpId, id: idpInformation.idpId,
userId: idpInformation.userId, userId: idpInformation.userId,
@@ -121,20 +131,23 @@ export default async function Page(props: {
const email = PROVIDER_MAPPING[providerType](idpInformation).email?.email; const email = PROVIDER_MAPPING[providerType](idpInformation).email?.email;
if (options.autoLinking === AutoLinkingOption.EMAIL && email) { if (options.autoLinking === AutoLinkingOption.EMAIL && email) {
foundUser = await listUsers({ serviceUrl, email }).then((response) => { foundUser = await listUsers({ serviceUrl, serviceRegion, email }).then(
return response.result ? response.result[0] : null; (response) => {
}); return response.result ? response.result[0] : null;
},
);
} else if (options.autoLinking === AutoLinkingOption.USERNAME) { } else if (options.autoLinking === AutoLinkingOption.USERNAME) {
foundUser = await listUsers( foundUser = await listUsers(
options.autoLinking === AutoLinkingOption.USERNAME options.autoLinking === AutoLinkingOption.USERNAME
? { serviceUrl, userName: idpInformation.userName } ? { serviceUrl, serviceRegion, userName: idpInformation.userName }
: { serviceUrl, email }, : { serviceUrl, serviceRegion, email },
).then((response) => { ).then((response) => {
return response.result ? response.result[0] : null; return response.result ? response.result[0] : null;
}); });
} else { } else {
foundUser = await listUsers({ foundUser = await listUsers({
serviceUrl, serviceUrl,
serviceRegion,
userName: idpInformation.userName, userName: idpInformation.userName,
email, email,
}).then((response) => { }).then((response) => {
@@ -147,6 +160,7 @@ export default async function Page(props: {
try { try {
idpLink = await addIDPLink({ idpLink = await addIDPLink({
serviceUrl, serviceUrl,
serviceRegion,
idp: { idp: {
id: idpInformation.idpId, id: idpInformation.idpId,
userId: idpInformation.userId, userId: idpInformation.userId,
@@ -187,12 +201,17 @@ export default async function Page(props: {
const suffix = matched?.[1] ?? ""; const suffix = matched?.[1] ?? "";
// this just returns orgs where the suffix is set as primary domain // this just returns orgs where the suffix is set as primary domain
const orgs = await getOrgsByDomain({ serviceUrl, domain: suffix }); const orgs = await getOrgsByDomain({
serviceUrl,
serviceRegion,
domain: suffix,
});
const orgToCheckForDiscovery = const orgToCheckForDiscovery =
orgs.result && orgs.result.length === 1 ? orgs.result[0].id : undefined; orgs.result && orgs.result.length === 1 ? orgs.result[0].id : undefined;
const orgLoginSettings = await getLoginSettings({ const orgLoginSettings = await getLoginSettings({
serviceUrl, serviceUrl,
serviceRegion,
organization: orgToCheckForDiscovery, organization: orgToCheckForDiscovery,
}); });
if (orgLoginSettings?.allowDomainDiscovery) { if (orgLoginSettings?.allowDomainDiscovery) {
@@ -211,7 +230,11 @@ export default async function Page(props: {
}); });
} }
const newUser = await addHuman({ serviceUrl, request: userData }); const newUser = await addHuman({
serviceUrl,
serviceRegion,
request: userData,
});
if (newUser) { if (newUser) {
return ( return (

View File

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

View File

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

View File

@@ -19,10 +19,10 @@ export default async function Page(props: {
let { userId, organization } = searchParams; let { userId, organization } = searchParams;
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
if (!organization) { if (!organization) {
const org = await getDefaultOrg({ serviceUrl }); const org = await getDefaultOrg({ serviceUrl, serviceRegion });
if (!org) { if (!org) {
throw new Error("No default organization found"); throw new Error("No default organization found");
} }
@@ -30,12 +30,20 @@ export default async function Page(props: {
organization = org.id; organization = org.id;
} }
const branding = await getBrandingSettings({ serviceUrl, organization }); const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});
let user: User | undefined; let user: User | undefined;
let human: HumanUser | undefined; let human: HumanUser | undefined;
if (userId) { if (userId) {
const userResponse = await getUserByID({ serviceUrl, userId }); const userResponse = await getUserByID({
serviceUrl,
serviceRegion,
userId,
});
if (userResponse) { if (userResponse) {
user = userResponse.user; user = userResponse.user;
if (user?.type.case === "human") { if (user?.type.case === "human") {

View File

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

View File

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

View File

@@ -52,7 +52,7 @@ export default async function Page(props: {
} = searchParams; } = searchParams;
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const sessionWithData = sessionId const sessionWithData = sessionId
? await loadSessionById(serviceUrl, sessionId, organization) ? await loadSessionById(serviceUrl, sessionId, organization)
@@ -65,24 +65,24 @@ export default async function Page(props: {
throw Error("Could not get user id from session"); throw Error("Could not get user id from session");
} }
return listAuthenticationMethodTypes({ serviceUrl, userId }).then( return listAuthenticationMethodTypes({
(methods) => { serviceUrl,
return getUserByID({ serviceUrl, userId }).then((user) => { serviceRegion,
const humanUser = userId,
user.user?.type.case === "human" }).then((methods) => {
? user.user?.type.value return getUserByID({ serviceUrl, serviceRegion, userId }).then((user) => {
: undefined; const humanUser =
user.user?.type.case === "human" ? user.user?.type.value : undefined;
return { return {
factors: session?.factors, factors: session?.factors,
authMethods: methods.authMethodTypes ?? [], authMethods: methods.authMethodTypes ?? [],
phoneVerified: humanUser?.phone?.isVerified ?? false, phoneVerified: humanUser?.phone?.isVerified ?? false,
emailVerified: humanUser?.email?.isVerified ?? false, emailVerified: humanUser?.email?.isVerified ?? false,
expirationDate: session?.expirationDate, expirationDate: session?.expirationDate,
}; };
}); });
}, });
);
} }
async function loadSessionByLoginname( async function loadSessionByLoginname(
@@ -92,6 +92,7 @@ export default async function Page(props: {
) { ) {
return loadMostRecentSession({ return loadMostRecentSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionParams: { sessionParams: {
loginName, loginName,
organization, organization,
@@ -109,6 +110,7 @@ export default async function Page(props: {
const recent = await getSessionCookieById({ sessionId, organization }); const recent = await getSessionCookieById({ sessionId, organization });
return getSession({ return getSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionId: recent.id, sessionId: recent.id,
sessionToken: recent.token, sessionToken: recent.token,
}).then((sessionResponse) => { }).then((sessionResponse) => {
@@ -116,9 +118,14 @@ export default async function Page(props: {
}); });
} }
const branding = await getBrandingSettings({ serviceUrl, organization }); const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});
const loginSettings = await getLoginSettings({ const loginSettings = await getLoginSettings({
serviceUrl, serviceUrl,
serviceRegion,
organization: sessionWithData.factors?.user?.organizationId, 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 tError = await getTranslations({ locale, namespace: "error" });
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const host = _headers.get("host"); const host = _headers.get("host");
if (!host || typeof host !== "string") { if (!host || typeof host !== "string") {
@@ -47,6 +47,7 @@ export default async function Page(props: {
? await loadSessionById(serviceUrl, sessionId, organization) ? await loadSessionById(serviceUrl, sessionId, organization)
: await loadMostRecentSession({ : await loadMostRecentSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionParams: { loginName, organization }, sessionParams: { loginName, organization },
}); });
@@ -58,6 +59,7 @@ export default async function Page(props: {
const recent = await getSessionCookieById({ sessionId, organization }); const recent = await getSessionCookieById({ sessionId, organization });
return getSession({ return getSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionId: recent.id, sessionId: recent.id,
sessionToken: recent.token, sessionToken: recent.token,
}).then((response) => { }).then((response) => {
@@ -70,11 +72,13 @@ export default async function Page(props: {
// email links do not come with organization, thus we need to use the session's organization // email links do not come with organization, thus we need to use the session's organization
const branding = await getBrandingSettings({ const branding = await getBrandingSettings({
serviceUrl, serviceUrl,
serviceRegion,
organization: organization ?? session?.factors?.user?.organizationId, organization: organization ?? session?.factors?.user?.organizationId,
}); });
const loginSettings = await getLoginSettings({ const loginSettings = await getLoginSettings({
serviceUrl, serviceUrl,
serviceRegion,
organization: organization ?? session?.factors?.user?.organizationId, organization: organization ?? session?.factors?.user?.organizationId,
}); });

View File

@@ -34,13 +34,22 @@ export default async function Page(props: {
const { method } = params; const { method } = params;
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const branding = await getBrandingSettings({ serviceUrl, organization }); const branding = await getBrandingSettings({
const loginSettings = await getLoginSettings({ serviceUrl, organization }); serviceUrl,
serviceRegion,
organization,
});
const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization,
});
const session = await loadMostRecentSession({ const session = await loadMostRecentSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionParams: { sessionParams: {
loginName, loginName,
organization, organization,
@@ -50,7 +59,11 @@ export default async function Page(props: {
let totpResponse: RegisterTOTPResponse | undefined, error: Error | undefined; let totpResponse: RegisterTOTPResponse | undefined, error: Error | undefined;
if (session && session.factors?.user?.id) { if (session && session.factors?.user?.id) {
if (method === "time-based") { if (method === "time-based") {
await registerTOTP({ serviceUrl, userId: session.factors.user.id }) await registerTOTP({
serviceUrl,
serviceRegion,
userId: session.factors.user.id,
})
.then((resp) => { .then((resp) => {
if (resp) { if (resp) {
totpResponse = resp; totpResponse = resp;
@@ -61,18 +74,22 @@ export default async function Page(props: {
}); });
} else if (method === "sms") { } else if (method === "sms") {
// does not work // does not work
await addOTPSMS({ serviceUrl, userId: session.factors.user.id }).catch( await addOTPSMS({
(error) => { serviceUrl,
error = new Error("Could not add OTP via SMS"); serviceRegion,
}, userId: session.factors.user.id,
); }).catch((error) => {
error = new Error("Could not add OTP via SMS");
});
} else if (method === "email") { } else if (method === "email") {
// works // works
await addOTPEmail({ serviceUrl, userId: session.factors.user.id }).catch( await addOTPEmail({
(error) => { serviceUrl,
error = new Error("Could not add OTP via Email"); serviceRegion,
}, userId: session.factors.user.id,
); }).catch((error) => {
error = new Error("Could not add OTP via Email");
});
} else { } else {
throw new Error("Invalid method"); throw new Error("Invalid method");
} }

View File

@@ -5,11 +5,7 @@ import { UserAvatar } from "@/components/user-avatar";
import { getSessionCookieById } from "@/lib/cookies"; import { getSessionCookieById } from "@/lib/cookies";
import { getServiceUrlFromHeaders } from "@/lib/service"; import { getServiceUrlFromHeaders } from "@/lib/service";
import { loadMostRecentSession } from "@/lib/session"; import { loadMostRecentSession } from "@/lib/session";
import { import { getBrandingSettings, getSession } from "@/lib/zitadel";
getBrandingSettings,
getLoginSettings,
getSession,
} from "@/lib/zitadel";
import { getLocale, getTranslations } from "next-intl/server"; import { getLocale, getTranslations } from "next-intl/server";
import { headers } from "next/headers"; import { headers } from "next/headers";
@@ -25,12 +21,13 @@ export default async function Page(props: {
searchParams; searchParams;
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const sessionFactors = sessionId const sessionFactors = sessionId
? await loadSessionById(serviceUrl, sessionId, organization) ? await loadSessionById(serviceUrl, sessionId, organization)
: await loadMostRecentSession({ : await loadMostRecentSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionParams: { loginName, organization }, sessionParams: { loginName, organization },
}); });
@@ -42,6 +39,7 @@ export default async function Page(props: {
const recent = await getSessionCookieById({ sessionId, organization }); const recent = await getSessionCookieById({ sessionId, organization });
return getSession({ return getSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionId: recent.id, sessionId: recent.id,
sessionToken: recent.token, sessionToken: recent.token,
}).then((response) => { }).then((response) => {
@@ -51,9 +49,11 @@ export default async function Page(props: {
}); });
} }
const branding = await getBrandingSettings({ serviceUrl, organization }); const branding = await getBrandingSettings({
serviceUrl,
const loginSettings = await getLoginSettings({ serviceUrl, organization }); serviceRegion,
organization,
});
return ( return (
<DynamicTheme branding={branding}> <DynamicTheme branding={branding}>

View File

@@ -20,17 +20,22 @@ export default async function Page(props: {
searchParams; searchParams;
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const session = await loadMostRecentSession({ const session = await loadMostRecentSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionParams: { sessionParams: {
loginName, loginName,
organization, organization,
}, },
}); });
const branding = await getBrandingSettings({ serviceUrl, organization }); const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});
return ( return (
<DynamicTheme branding={branding}> <DynamicTheme branding={branding}>

View File

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

View File

@@ -25,11 +25,14 @@ export default async function Page(props: {
let { loginName, organization, authRequestId, alt } = searchParams; let { loginName, organization, authRequestId, alt } = searchParams;
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
let defaultOrganization; let defaultOrganization;
if (!organization) { if (!organization) {
const org: Organization | null = await getDefaultOrg({ serviceUrl }); const org: Organization | null = await getDefaultOrg({
serviceUrl,
serviceRegion,
});
if (org) { if (org) {
defaultOrganization = org.id; defaultOrganization = org.id;
@@ -41,6 +44,7 @@ export default async function Page(props: {
try { try {
sessionFactors = await loadMostRecentSession({ sessionFactors = await loadMostRecentSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionParams: { sessionParams: {
loginName, loginName,
organization, organization,
@@ -53,10 +57,12 @@ export default async function Page(props: {
const branding = await getBrandingSettings({ const branding = await getBrandingSettings({
serviceUrl, serviceUrl,
serviceRegion,
organization: organization ?? defaultOrganization, organization: organization ?? defaultOrganization,
}); });
const loginSettings = await getLoginSettings({ const loginSettings = await getLoginSettings({
serviceUrl, serviceUrl,
serviceRegion,
organization: organization ?? defaultOrganization, organization: organization ?? defaultOrganization,
}); });

View File

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

View File

@@ -23,24 +23,40 @@ export default async function Page(props: {
searchParams; searchParams;
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
if (!organization) { if (!organization) {
const org: Organization | null = await getDefaultOrg({ serviceUrl }); const org: Organization | null = await getDefaultOrg({
serviceUrl,
serviceRegion,
});
if (org) { if (org) {
organization = org.id; organization = org.id;
} }
} }
const legal = await getLegalAndSupportSettings({ serviceUrl, organization }); const legal = await getLegalAndSupportSettings({
serviceUrl,
serviceRegion,
organization,
});
const passwordComplexitySettings = await getPasswordComplexitySettings({ const passwordComplexitySettings = await getPasswordComplexitySettings({
serviceUrl, serviceUrl,
serviceRegion,
organization, organization,
}); });
const branding = await getBrandingSettings({ serviceUrl, organization }); const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});
const loginSettings = await getLoginSettings({ serviceUrl, organization }); const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization,
});
if (!loginSettings?.allowRegister) { if (!loginSettings?.allowRegister) {
return ( return (

View File

@@ -23,10 +23,13 @@ export default async function Page(props: {
searchParams; searchParams;
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
if (!organization) { if (!organization) {
const org: Organization | null = await getDefaultOrg({ serviceUrl }); const org: Organization | null = await getDefaultOrg({
serviceUrl,
serviceRegion,
});
if (org) { if (org) {
organization = org.id; organization = org.id;
} }
@@ -34,15 +37,28 @@ export default async function Page(props: {
const missingData = !firstname || !lastname || !email; const missingData = !firstname || !lastname || !email;
const legal = await getLegalAndSupportSettings({ serviceUrl, organization }); const legal = await getLegalAndSupportSettings({
serviceUrl,
serviceRegion,
organization,
});
const passwordComplexitySettings = await getPasswordComplexitySettings({ const passwordComplexitySettings = await getPasswordComplexitySettings({
serviceUrl, serviceUrl,
serviceRegion,
organization, organization,
}); });
const branding = await getBrandingSettings({ serviceUrl, organization }); const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});
const loginSettings = await getLoginSettings({ serviceUrl, organization }); const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization,
});
return missingData ? ( return missingData ? (
<DynamicTheme branding={branding}> <DynamicTheme branding={branding}>

View File

@@ -22,6 +22,7 @@ import { redirect } from "next/navigation";
async function loadSession( async function loadSession(
serviceUrl: string, serviceUrl: string,
serviceRegion: string,
loginName: string, loginName: string,
authRequestId?: string, authRequestId?: string,
) { ) {
@@ -30,6 +31,7 @@ async function loadSession(
if (authRequestId) { if (authRequestId) {
return createCallback({ return createCallback({
serviceUrl, serviceUrl,
serviceRegion,
req: create(CreateCallbackRequestSchema, { req: create(CreateCallbackRequestSchema, {
authRequestId, authRequestId,
callbackKind: { callbackKind: {
@@ -46,6 +48,7 @@ async function loadSession(
} }
return getSession({ return getSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionId: recent.id, sessionId: recent.id,
sessionToken: recent.token, sessionToken: recent.token,
}).then((response) => { }).then((response) => {
@@ -61,20 +64,29 @@ export default async function Page(props: { searchParams: Promise<any> }) {
const t = await getTranslations({ locale, namespace: "signedin" }); const t = await getTranslations({ locale, namespace: "signedin" });
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { loginName, authRequestId, organization } = searchParams; const { loginName, authRequestId, organization } = searchParams;
const sessionFactors = await loadSession( const sessionFactors = await loadSession(
serviceUrl, serviceUrl,
serviceRegion,
loginName, loginName,
authRequestId, authRequestId,
); );
const branding = await getBrandingSettings({ serviceUrl, organization }); const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});
let loginSettings; let loginSettings;
if (!authRequestId) { if (!authRequestId) {
loginSettings = await getLoginSettings({ serviceUrl, organization }); loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization,
});
} }
return ( return (

View File

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

View File

@@ -19,17 +19,22 @@ export default async function Page(props: {
const { loginName, organization, authRequestId, checkAfter } = searchParams; const { loginName, organization, authRequestId, checkAfter } = searchParams;
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const sessionFactors = await loadMostRecentSession({ const sessionFactors = await loadMostRecentSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionParams: { sessionParams: {
loginName, loginName,
organization, organization,
}, },
}); });
const branding = await getBrandingSettings({ serviceUrl, organization }); const branding = await getBrandingSettings({
serviceUrl,
serviceRegion,
organization,
});
return ( return (
<DynamicTheme branding={branding}> <DynamicTheme branding={branding}>

View File

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

View File

@@ -32,13 +32,16 @@ export const fetchCache = "default-no-store";
async function loadSessions({ async function loadSessions({
serviceUrl, serviceUrl,
serviceRegion,
ids, ids,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
ids: string[]; ids: string[];
}): Promise<Session[]> { }): Promise<Session[]> {
const response = await listSessions({ const response = await listSessions({
serviceUrl, serviceUrl,
serviceRegion,
ids: ids.filter((id: string | undefined) => !!id), ids: ids.filter((id: string | undefined) => !!id),
}); });
@@ -55,6 +58,7 @@ const IDP_SCOPE_REGEX = /urn:zitadel:iam:org:idp:id:(.+)/;
**/ **/
async function isSessionValid( async function isSessionValid(
serviceUrl: string, serviceUrl: string,
serviceRegion: string,
session: Session, session: Session,
): Promise<boolean> { ): Promise<boolean> {
// session can't be checked without user // session can't be checked without user
@@ -67,6 +71,7 @@ async function isSessionValid(
const authMethodTypes = await listAuthenticationMethodTypes({ const authMethodTypes = await listAuthenticationMethodTypes({
serviceUrl, serviceUrl,
serviceRegion,
userId: session.factors.user.id, userId: session.factors.user.id,
}); });
@@ -116,6 +121,7 @@ async function isSessionValid(
// only check settings if no auth methods are available, as this would require a setup // only check settings if no auth methods are available, as this would require a setup
const loginSettings = await getLoginSettings({ const loginSettings = await getLoginSettings({
serviceUrl, serviceUrl,
serviceRegion,
organization: session.factors?.user?.organizationId, organization: session.factors?.user?.organizationId,
}); });
if (loginSettings?.forceMfa || loginSettings?.forceMfaLocalOnly) { if (loginSettings?.forceMfa || loginSettings?.forceMfaLocalOnly) {
@@ -159,6 +165,7 @@ async function isSessionValid(
async function findValidSession( async function findValidSession(
serviceUrl: string, serviceUrl: string,
serviceRegion: string,
sessions: Session[], sessions: Session[],
authRequest: AuthRequest, authRequest: AuthRequest,
): Promise<Session | undefined> { ): Promise<Session | undefined> {
@@ -185,7 +192,7 @@ async function findValidSession(
// return the first valid session according to settings // return the first valid session according to settings
for (const session of sessionsWithHint) { for (const session of sessionsWithHint) {
if (await isSessionValid(serviceUrl, session)) { if (await isSessionValid(serviceUrl, serviceRegion, session)) {
return session; return session;
} }
} }
@@ -199,7 +206,7 @@ export async function GET(request: NextRequest) {
const sessionId = searchParams.get("sessionId"); const sessionId = searchParams.get("sessionId");
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
// TODO: find a better way to handle _rsc (react server components) requests and block them to avoid conflicts when creating oidc callback // TODO: find a better way to handle _rsc (react server components) requests and block them to avoid conflicts when creating oidc callback
const _rsc = searchParams.get("_rsc"); const _rsc = searchParams.get("_rsc");
@@ -211,7 +218,7 @@ export async function GET(request: NextRequest) {
const ids = sessionCookies.map((s) => s.id); const ids = sessionCookies.map((s) => s.id);
let sessions: Session[] = []; let sessions: Session[] = [];
if (ids && ids.length) { if (ids && ids.length) {
sessions = await loadSessions({ serviceUrl, ids }); sessions = await loadSessions({ serviceUrl, serviceRegion, ids });
} }
if (authRequestId && sessionId) { if (authRequestId && sessionId) {
@@ -224,7 +231,11 @@ export async function GET(request: NextRequest) {
if (selectedSession && selectedSession.id) { if (selectedSession && selectedSession.id) {
console.log(`Found session ${selectedSession.id}`); console.log(`Found session ${selectedSession.id}`);
const isValid = await isSessionValid(serviceUrl, selectedSession); const isValid = await isSessionValid(
serviceUrl,
serviceRegion,
selectedSession,
);
console.log("Session is valid:", isValid); console.log("Session is valid:", isValid);
@@ -259,6 +270,7 @@ export async function GET(request: NextRequest) {
try { try {
const { callbackUrl } = await createCallback({ const { callbackUrl } = await createCallback({
serviceUrl, serviceUrl,
serviceRegion,
req: create(CreateCallbackRequestSchema, { req: create(CreateCallbackRequestSchema, {
authRequestId, authRequestId,
callbackKind: { callbackKind: {
@@ -286,6 +298,7 @@ export async function GET(request: NextRequest) {
) { ) {
const loginSettings = await getLoginSettings({ const loginSettings = await getLoginSettings({
serviceUrl, serviceUrl,
serviceRegion,
organization: selectedSession.factors?.user?.organizationId, organization: selectedSession.factors?.user?.organizationId,
}); });
@@ -317,7 +330,11 @@ export async function GET(request: NextRequest) {
} }
if (authRequestId) { if (authRequestId) {
const { authRequest } = await getAuthRequest({ serviceUrl, authRequestId }); const { authRequest } = await getAuthRequest({
serviceUrl,
serviceRegion,
authRequestId,
});
let organization = ""; let organization = "";
let suffix = ""; let suffix = "";
@@ -346,6 +363,7 @@ export async function GET(request: NextRequest) {
if (orgDomain) { if (orgDomain) {
const orgs = await getOrgsByDomain({ const orgs = await getOrgsByDomain({
serviceUrl, serviceUrl,
serviceRegion,
domain: orgDomain, domain: orgDomain,
}); });
if (orgs.result && orgs.result.length === 1) { if (orgs.result && orgs.result.length === 1) {
@@ -362,6 +380,7 @@ export async function GET(request: NextRequest) {
const identityProviders = await getActiveIdentityProviders({ const identityProviders = await getActiveIdentityProviders({
serviceUrl, serviceUrl,
serviceRegion,
orgId: organization ? organization : undefined, orgId: organization ? organization : undefined,
}).then((resp) => { }).then((resp) => {
return resp.identityProviders; return resp.identityProviders;
@@ -387,6 +406,7 @@ export async function GET(request: NextRequest) {
return startIdentityProviderFlow({ return startIdentityProviderFlow({
serviceUrl, serviceUrl,
serviceRegion,
idpId, idpId,
urls: { urls: {
successUrl: successUrl:
@@ -487,6 +507,7 @@ export async function GET(request: NextRequest) {
**/ **/
const selectedSession = await findValidSession( const selectedSession = await findValidSession(
serviceUrl, serviceUrl,
serviceRegion,
sessions, sessions,
authRequest, authRequest,
); );
@@ -516,6 +537,7 @@ export async function GET(request: NextRequest) {
const { callbackUrl } = await createCallback({ const { callbackUrl } = await createCallback({
serviceUrl, serviceUrl,
serviceRegion,
req: create(CreateCallbackRequestSchema, { req: create(CreateCallbackRequestSchema, {
authRequestId, authRequestId,
callbackKind: { callbackKind: {
@@ -529,6 +551,7 @@ export async function GET(request: NextRequest) {
// check for loginHint, userId hint and valid sessions // check for loginHint, userId hint and valid sessions
let selectedSession = await findValidSession( let selectedSession = await findValidSession(
serviceUrl, serviceUrl,
serviceRegion,
sessions, sessions,
authRequest, authRequest,
); );
@@ -553,6 +576,7 @@ export async function GET(request: NextRequest) {
try { try {
const { callbackUrl } = await createCallback({ const { callbackUrl } = await createCallback({
serviceUrl, serviceUrl,
serviceRegion,
req: create(CreateCallbackRequestSchema, { req: create(CreateCallbackRequestSchema, {
authRequestId, authRequestId,
callbackKind: { callbackKind: {

View File

@@ -1,17 +1,40 @@
import { newSystemToken } from "@zitadel/client/node"; import { newSystemToken } from "@zitadel/client/node";
export async function systemAPIToken() { export async function systemAPIToken({
const audience = process.env.AUDIENCE; serviceRegion,
const userID = process.env.SYSTEM_USER_ID; }: {
const key = process.env.SYSTEM_USER_PRIVATE_KEY; serviceRegion: string;
}) {
const prefix = serviceRegion.toUpperCase();
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"),
};
const decodedToken = Buffer.from(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"),
};
const token = newSystemToken({ return newSystemToken({
audience: audience, audience: fallbackToken.audience,
subject: userID, subject: fallbackToken.userID,
key: decodedToken, key: fallbackToken.token,
});
}
return newSystemToken({
audience: token.audience,
subject: token.userID,
key: token.token,
}); });
return token;
} }

View File

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

View File

@@ -35,10 +35,11 @@ export async function createSessionAndUpdateCookie(
lifetime?: Duration, lifetime?: Duration,
): Promise<Session> { ): Promise<Session> {
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const createdSession = await createSessionFromChecks({ const createdSession = await createSessionFromChecks({
serviceUrl, serviceUrl,
serviceRegion,
checks, checks,
challenges, challenges,
lifetime, lifetime,
@@ -47,6 +48,7 @@ export async function createSessionAndUpdateCookie(
if (createdSession) { if (createdSession) {
return getSession({ return getSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionId: createdSession.sessionId, sessionId: createdSession.sessionId,
sessionToken: createdSession.sessionToken, sessionToken: createdSession.sessionToken,
}).then((response) => { }).then((response) => {
@@ -97,10 +99,11 @@ export async function createSessionForIdpAndUpdateCookie(
lifetime?: Duration, lifetime?: Duration,
): Promise<Session> { ): Promise<Session> {
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const createdSession = await createSessionForUserIdAndIdpIntent({ const createdSession = await createSessionForUserIdAndIdpIntent({
serviceUrl, serviceUrl,
serviceRegion,
userId, userId,
idpIntent, idpIntent,
lifetime, lifetime,
@@ -112,6 +115,7 @@ export async function createSessionForIdpAndUpdateCookie(
const { session } = await getSession({ const { session } = await getSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionId: createdSession.sessionId, sessionId: createdSession.sessionId,
sessionToken: createdSession.sessionToken, sessionToken: createdSession.sessionToken,
}); });
@@ -159,10 +163,11 @@ export async function setSessionAndUpdateCookie(
lifetime?: Duration, lifetime?: Duration,
) { ) {
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
return setSession({ return setSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionId: recentCookie.id, sessionId: recentCookie.id,
sessionToken: recentCookie.token, sessionToken: recentCookie.token,
challenges, challenges,
@@ -189,6 +194,7 @@ export async function setSessionAndUpdateCookie(
return getSession({ return getSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionId: sessionCookie.id, sessionId: sessionCookie.id,
sessionToken: sessionCookie.token, sessionToken: sessionCookie.token,
}).then((response) => { }).then((response) => {

View File

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

View File

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

View File

@@ -34,7 +34,7 @@ const ORG_SUFFIX_REGEX = /(?<=@)(.+)/;
export async function sendLoginname(command: SendLoginnameCommand) { export async function sendLoginname(command: SendLoginnameCommand) {
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const host = _headers.get("host"); const host = _headers.get("host");
if (!host) { if (!host) {
@@ -43,6 +43,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
const loginSettingsByContext = await getLoginSettings({ const loginSettingsByContext = await getLoginSettings({
serviceUrl, serviceUrl,
serviceRegion,
organization: command.organization, organization: command.organization,
}); });
@@ -52,6 +53,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
let searchUsersRequest: SearchUsersCommand = { let searchUsersRequest: SearchUsersCommand = {
serviceUrl, serviceUrl,
serviceRegion,
searchValue: command.loginName, searchValue: command.loginName,
organizationId: command.organization, organizationId: command.organization,
loginSettings: loginSettingsByContext, loginSettings: loginSettingsByContext,
@@ -73,6 +75,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
const redirectUserToSingleIDPIfAvailable = async () => { const redirectUserToSingleIDPIfAvailable = async () => {
const identityProviders = await getActiveIdentityProviders({ const identityProviders = await getActiveIdentityProviders({
serviceUrl, serviceUrl,
serviceRegion,
orgId: command.organization, orgId: command.organization,
}).then((resp) => { }).then((resp) => {
return resp.identityProviders; return resp.identityProviders;
@@ -80,7 +83,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
if (identityProviders.length === 1) { if (identityProviders.length === 1) {
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const host = _headers.get("host"); const host = _headers.get("host");
if (!host) { if (!host) {
@@ -103,6 +106,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
const resp = await startIdentityProviderFlow({ const resp = await startIdentityProviderFlow({
serviceUrl, serviceUrl,
serviceRegion,
idpId: identityProviders[0].id, idpId: identityProviders[0].id,
urls: { urls: {
successUrl: successUrl:
@@ -121,15 +125,17 @@ export async function sendLoginname(command: SendLoginnameCommand) {
}; };
const redirectUserToIDP = async (userId: string) => { const redirectUserToIDP = async (userId: string) => {
const identityProviders = await listIDPLinks({ serviceUrl, userId }).then( const identityProviders = await listIDPLinks({
(resp) => { serviceUrl,
return resp.result; serviceRegion,
}, userId,
); }).then((resp) => {
return resp.result;
});
if (identityProviders.length === 1) { if (identityProviders.length === 1) {
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const host = _headers.get("host"); const host = _headers.get("host");
if (!host) { if (!host) {
@@ -138,7 +144,11 @@ export async function sendLoginname(command: SendLoginnameCommand) {
const identityProviderId = identityProviders[0].idpId; const identityProviderId = identityProviders[0].idpId;
const idp = await getIDPByID({ serviceUrl, id: identityProviderId }); const idp = await getIDPByID({
serviceUrl,
serviceRegion,
id: identityProviderId,
});
const idpType = idp?.type; const idpType = idp?.type;
@@ -161,6 +171,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
const resp = await startIdentityProviderFlow({ const resp = await startIdentityProviderFlow({
serviceUrl, serviceUrl,
serviceRegion,
idpId: idp.id, idpId: idp.id,
urls: { urls: {
successUrl: successUrl:
@@ -186,6 +197,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
const userLoginSettings = await getLoginSettings({ const userLoginSettings = await getLoginSettings({
serviceUrl, serviceUrl,
serviceRegion,
organization: user.details?.resourceOwner, organization: user.details?.resourceOwner,
}); });
@@ -244,6 +256,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
const methods = await listAuthenticationMethodTypes({ const methods = await listAuthenticationMethodTypes({
serviceUrl, serviceUrl,
serviceRegion,
userId: session.factors?.user?.id, userId: session.factors?.user?.id,
}); });
@@ -400,12 +413,17 @@ export async function sendLoginname(command: SendLoginnameCommand) {
const suffix = matched?.[1] ?? ""; const suffix = matched?.[1] ?? "";
// this just returns orgs where the suffix is set as primary domain // this just returns orgs where the suffix is set as primary domain
const orgs = await getOrgsByDomain({ serviceUrl, domain: suffix }); const orgs = await getOrgsByDomain({
serviceUrl,
serviceRegion,
domain: suffix,
});
const orgToCheckForDiscovery = const orgToCheckForDiscovery =
orgs.result && orgs.result.length === 1 ? orgs.result[0].id : undefined; orgs.result && orgs.result.length === 1 ? orgs.result[0].id : undefined;
const orgLoginSettings = await getLoginSettings({ const orgLoginSettings = await getLoginSettings({
serviceUrl, serviceUrl,
serviceRegion,
organization: orgToCheckForDiscovery, organization: orgToCheckForDiscovery,
}); });
if (orgLoginSettings?.allowDomainDiscovery) { if (orgLoginSettings?.allowDomainDiscovery) {

View File

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

View File

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

View File

@@ -45,7 +45,7 @@ type ResetPasswordCommand = {
export async function resetPassword(command: ResetPasswordCommand) { export async function resetPassword(command: ResetPasswordCommand) {
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const host = _headers.get("host"); const host = _headers.get("host");
if (!host || typeof host !== "string") { if (!host || typeof host !== "string") {
@@ -54,6 +54,7 @@ export async function resetPassword(command: ResetPasswordCommand) {
const users = await listUsers({ const users = await listUsers({
serviceUrl, serviceUrl,
serviceRegion,
loginName: command.loginName, loginName: command.loginName,
organizationId: command.organization, organizationId: command.organization,
}); });
@@ -69,6 +70,7 @@ export async function resetPassword(command: ResetPasswordCommand) {
return passwordReset({ return passwordReset({
serviceUrl, serviceUrl,
serviceRegion,
userId, userId,
urlTemplate: urlTemplate:
`${host.includes("localhost") ? "http://" : "https://"}${host}/password/set?code={{.Code}}&userId={{.UserID}}&organization={{.OrgID}}` + `${host.includes("localhost") ? "http://" : "https://"}${host}/password/set?code={{.Code}}&userId={{.UserID}}&organization={{.OrgID}}` +
@@ -85,7 +87,7 @@ export type UpdateSessionCommand = {
export async function sendPassword(command: UpdateSessionCommand) { export async function sendPassword(command: UpdateSessionCommand) {
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
let sessionCookie = await getSessionCookieByLoginName({ let sessionCookie = await getSessionCookieByLoginName({
loginName: command.loginName, loginName: command.loginName,
@@ -101,6 +103,7 @@ export async function sendPassword(command: UpdateSessionCommand) {
if (!sessionCookie) { if (!sessionCookie) {
const users = await listUsers({ const users = await listUsers({
serviceUrl, serviceUrl,
serviceRegion,
loginName: command.loginName, loginName: command.loginName,
organizationId: command.organization, organizationId: command.organization,
}); });
@@ -115,6 +118,7 @@ export async function sendPassword(command: UpdateSessionCommand) {
loginSettings = await getLoginSettings({ loginSettings = await getLoginSettings({
serviceUrl, serviceUrl,
serviceRegion,
organization: command.organization, organization: command.organization,
}); });
@@ -143,6 +147,7 @@ export async function sendPassword(command: UpdateSessionCommand) {
const userResponse = await getUserByID({ const userResponse = await getUserByID({
serviceUrl, serviceUrl,
serviceRegion,
userId: session?.factors?.user?.id, userId: session?.factors?.user?.id,
}); });
@@ -156,6 +161,7 @@ export async function sendPassword(command: UpdateSessionCommand) {
if (!loginSettings) { if (!loginSettings) {
loginSettings = await getLoginSettings({ loginSettings = await getLoginSettings({
serviceUrl, serviceUrl,
serviceRegion,
organization: organization:
command.organization ?? session.factors?.user?.organizationId, command.organization ?? session.factors?.user?.organizationId,
}); });
@@ -201,6 +207,7 @@ export async function sendPassword(command: UpdateSessionCommand) {
if (command.checks && command.checks.password && session.factors?.user?.id) { if (command.checks && command.checks.password && session.factors?.user?.id) {
const response = await listAuthenticationMethodTypes({ const response = await listAuthenticationMethodTypes({
serviceUrl, serviceUrl,
serviceRegion,
userId: session.factors.user.id, userId: session.factors.user.id,
}); });
if (response.authMethodTypes && response.authMethodTypes.length) { if (response.authMethodTypes && response.authMethodTypes.length) {
@@ -255,10 +262,14 @@ export async function changePassword(command: {
password: string; password: string;
}) { }) {
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
// check for init state // check for init state
const { user } = await getUserByID({ serviceUrl, userId: command.userId }); const { user } = await getUserByID({
serviceUrl,
serviceRegion,
userId: command.userId,
});
if (!user || user.userId !== command.userId) { if (!user || user.userId !== command.userId) {
return { error: "Could not send Password Reset Link" }; return { error: "Could not send Password Reset Link" };
@@ -267,6 +278,7 @@ export async function changePassword(command: {
return setUserPassword({ return setUserPassword({
serviceUrl, serviceUrl,
serviceRegion,
userId, userId,
password: command.password, password: command.password,
user, user,
@@ -284,12 +296,13 @@ export async function checkSessionAndSetPassword({
password, password,
}: CheckSessionAndSetPasswordCommand) { }: CheckSessionAndSetPasswordCommand) {
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const sessionCookie = await getSessionCookieById({ sessionId }); const sessionCookie = await getSessionCookieById({ sessionId });
const { session } = await getSession({ const { session } = await getSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionId: sessionCookie.id, sessionId: sessionCookie.id,
sessionToken: sessionCookie.token, sessionToken: sessionCookie.token,
}); });
@@ -308,6 +321,7 @@ export async function checkSessionAndSetPassword({
// check if the user has no password set in order to set a password // check if the user has no password set in order to set a password
const authmethods = await listAuthenticationMethodTypes({ const authmethods = await listAuthenticationMethodTypes({
serviceUrl, serviceUrl,
serviceRegion,
userId: session.factors.user.id, userId: session.factors.user.id,
}); });
@@ -328,6 +342,7 @@ export async function checkSessionAndSetPassword({
const loginSettings = await getLoginSettings({ const loginSettings = await getLoginSettings({
serviceUrl, serviceUrl,
serviceRegion,
organization: session.factors.user.organizationId, organization: session.factors.user.organizationId,
}); });
@@ -337,22 +352,24 @@ 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 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) { if (forceMfa && hasNoMFAMethods) {
return setPassword({ serviceUrl, payload }).catch((error) => { return setPassword({ serviceUrl, serviceRegion, payload }).catch(
// throw error if failed precondition (ex. User is not yet initialized) (error) => {
if (error.code === 9 && error.message) { // throw error if failed precondition (ex. User is not yet initialized)
return { error: "Failed precondition" }; if (error.code === 9 && error.message) {
} else { return { error: "Failed precondition" };
throw error; } else {
} throw error;
}); }
},
);
} else { } else {
const transport = async (host: string, token: string) => { const transport = async (serviceUrl: string, token: string) => {
return createServerTransport(token, { return createServerTransport(token, {
baseUrl: serviceUrl, baseUrl: serviceUrl,
}); });
}; };
const myUserService = async (host: string, sessionToken: string) => { const myUserService = async (serviceUrl: string, sessionToken: string) => {
const transportPromise = await transport(serviceUrl, sessionToken); const transportPromise = await transport(serviceUrl, sessionToken);
return createUserServiceClient(transportPromise); return createUserServiceClient(transportPromise);
}; };

View File

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

View File

@@ -25,10 +25,11 @@ export async function continueWithSession({
...session ...session
}: Session & { authRequestId?: string }) { }: Session & { authRequestId?: string }) {
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const loginSettings = await getLoginSettings({ const loginSettings = await getLoginSettings({
serviceUrl, serviceUrl,
serviceRegion,
organization: session.factors?.user?.organizationId, organization: session.factors?.user?.organizationId,
}); });
@@ -88,7 +89,7 @@ export async function updateSession(options: UpdateSessionCommand) {
} }
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const host = _headers.get("host"); const host = _headers.get("host");
if (!host) { if (!host) {
@@ -106,7 +107,11 @@ export async function updateSession(options: UpdateSessionCommand) {
challenges.webAuthN.domain = hostname; challenges.webAuthN.domain = hostname;
} }
const loginSettings = await getLoginSettings({ serviceUrl, organization }); const loginSettings = await getLoginSettings({
serviceUrl,
serviceRegion,
organization,
});
const lifetime = checks?.webAuthN const lifetime = checks?.webAuthN
? loginSettings?.multiFactorCheckLifetime // TODO different lifetime for webauthn u2f/passkey ? loginSettings?.multiFactorCheckLifetime // TODO different lifetime for webauthn u2f/passkey
@@ -131,6 +136,7 @@ export async function updateSession(options: UpdateSessionCommand) {
if (checks && checks.password && session.factors?.user?.id) { if (checks && checks.password && session.factors?.user?.id) {
const response = await listAuthenticationMethodTypes({ const response = await listAuthenticationMethodTypes({
serviceUrl, serviceUrl,
serviceRegion,
userId: session.factors.user.id, userId: session.factors.user.id,
}); });
if (response.authMethodTypes && response.authMethodTypes.length) { if (response.authMethodTypes && response.authMethodTypes.length) {
@@ -152,7 +158,7 @@ type ClearSessionOptions = {
export async function clearSession(options: ClearSessionOptions) { export async function clearSession(options: ClearSessionOptions) {
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const { sessionId } = options; const { sessionId } = options;
@@ -160,6 +166,7 @@ export async function clearSession(options: ClearSessionOptions) {
const deletedSession = await deleteSession({ const deletedSession = await deleteSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionId: session.id, sessionId: session.id,
sessionToken: session.token, sessionToken: session.token,
}); });
@@ -175,12 +182,13 @@ type CleanupSessionCommand = {
export async function cleanupSession({ sessionId }: CleanupSessionCommand) { export async function cleanupSession({ sessionId }: CleanupSessionCommand) {
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const sessionCookie = await getSessionCookieById({ sessionId }); const sessionCookie = await getSessionCookieById({ sessionId });
const deleteResponse = await deleteSession({ const deleteResponse = await deleteSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionId: sessionCookie.id, sessionId: sessionCookie.id,
sessionToken: sessionCookie.token, sessionToken: sessionCookie.token,
}); });

View File

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

View File

@@ -30,10 +30,11 @@ export async function verifyTOTP(
organization?: string, organization?: string,
) { ) {
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
return loadMostRecentSession({ return loadMostRecentSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionParams: { sessionParams: {
loginName, loginName,
organization, organization,
@@ -42,6 +43,7 @@ export async function verifyTOTP(
if (session?.factors?.user?.id) { if (session?.factors?.user?.id) {
return verifyTOTPRegistration({ return verifyTOTPRegistration({
serviceUrl, serviceUrl,
serviceRegion,
code, code,
userId: session.factors.user.id, userId: session.factors.user.id,
}); });
@@ -62,11 +64,12 @@ type VerifyUserByEmailCommand = {
export async function sendVerification(command: VerifyUserByEmailCommand) { export async function sendVerification(command: VerifyUserByEmailCommand) {
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const verifyResponse = command.isInvite const verifyResponse = command.isInvite
? await verifyInviteCode({ ? await verifyInviteCode({
serviceUrl, serviceUrl,
serviceRegion,
userId: command.userId, userId: command.userId,
verificationCode: command.code, verificationCode: command.code,
}).catch(() => { }).catch(() => {
@@ -74,6 +77,7 @@ export async function sendVerification(command: VerifyUserByEmailCommand) {
}) })
: await verifyEmail({ : await verifyEmail({
serviceUrl, serviceUrl,
serviceRegion,
userId: command.userId, userId: command.userId,
verificationCode: command.code, verificationCode: command.code,
}).catch(() => { }).catch(() => {
@@ -105,6 +109,7 @@ export async function sendVerification(command: VerifyUserByEmailCommand) {
session = await getSession({ session = await getSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionId: sessionCookie.id, sessionId: sessionCookie.id,
sessionToken: sessionCookie.token, sessionToken: sessionCookie.token,
}).then((response) => { }).then((response) => {
@@ -119,6 +124,7 @@ export async function sendVerification(command: VerifyUserByEmailCommand) {
const userResponse = await getUserByID({ const userResponse = await getUserByID({
serviceUrl, serviceUrl,
serviceRegion,
userId: session?.factors?.user?.id, userId: session?.factors?.user?.id,
}); });
@@ -130,6 +136,7 @@ export async function sendVerification(command: VerifyUserByEmailCommand) {
} else { } else {
const userResponse = await getUserByID({ const userResponse = await getUserByID({
serviceUrl, serviceUrl,
serviceRegion,
userId: command.userId, userId: command.userId,
}); });
@@ -169,11 +176,13 @@ export async function sendVerification(command: VerifyUserByEmailCommand) {
const loginSettings = await getLoginSettings({ const loginSettings = await getLoginSettings({
serviceUrl, serviceUrl,
serviceRegion,
organization: user.details?.resourceOwner, organization: user.details?.resourceOwner,
}); });
const authMethodResponse = await listAuthenticationMethodTypes({ const authMethodResponse = await listAuthenticationMethodTypes({
serviceUrl, serviceUrl,
serviceRegion,
userId: user.userId, userId: user.userId,
}); });
@@ -244,7 +253,7 @@ type resendVerifyEmailCommand = {
export async function resendVerification(command: resendVerifyEmailCommand) { export async function resendVerification(command: resendVerifyEmailCommand) {
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
const host = _headers.get("host"); const host = _headers.get("host");
if (!host) { if (!host) {
@@ -252,10 +261,11 @@ export async function resendVerification(command: resendVerifyEmailCommand) {
} }
return command.isInvite return command.isInvite
? resendInviteCode({ serviceUrl, userId: command.userId }) ? resendInviteCode({ serviceUrl, serviceRegion, userId: command.userId })
: resendEmailCode({ : resendEmailCode({
userId: command.userId, userId: command.userId,
serviceUrl, serviceUrl,
serviceRegion,
urlTemplate: urlTemplate:
`${host.includes("localhost") ? "http://" : "https://"}${host}/password/set?code={{.Code}}&userId={{.UserID}}&organization={{.OrgID}}` + `${host.includes("localhost") ? "http://" : "https://"}${host}/password/set?code={{.Code}}&userId={{.UserID}}&organization={{.OrgID}}` +
(command.authRequestId (command.authRequestId
@@ -266,14 +276,16 @@ export async function resendVerification(command: resendVerifyEmailCommand) {
type sendEmailCommand = { type sendEmailCommand = {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
userId: string; userId: string;
urlTemplate: string; urlTemplate: string;
}; };
export async function sendEmailCode(command: sendEmailCommand) { export async function sendEmailCode(command: sendEmailCommand) {
return zitadelSendEmailCode({ return zitadelSendEmailCode({
userId: command.userId,
serviceUrl: command.serviceUrl, serviceUrl: command.serviceUrl,
serviceRegion: command.serviceRegion,
userId: command.userId,
urlTemplate: command.urlTemplate, urlTemplate: command.urlTemplate,
}); });
} }
@@ -290,7 +302,7 @@ export async function sendVerificationRedirectWithoutCheck(
command: SendVerificationRedirectWithoutCheckCommand, command: SendVerificationRedirectWithoutCheckCommand,
) { ) {
const _headers = await headers(); const _headers = await headers();
const serviceUrl = getServiceUrlFromHeaders(_headers); const { serviceUrl, serviceRegion } = getServiceUrlFromHeaders(_headers);
if (!("loginName" in command || "userId" in command)) { if (!("loginName" in command || "userId" in command)) {
return { error: "No userId, nor loginname provided" }; return { error: "No userId, nor loginname provided" };
@@ -313,6 +325,7 @@ export async function sendVerificationRedirectWithoutCheck(
session = await getSession({ session = await getSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionId: sessionCookie.id, sessionId: sessionCookie.id,
sessionToken: sessionCookie.token, sessionToken: sessionCookie.token,
}).then((response) => { }).then((response) => {
@@ -327,6 +340,7 @@ export async function sendVerificationRedirectWithoutCheck(
const userResponse = await getUserByID({ const userResponse = await getUserByID({
serviceUrl, serviceUrl,
serviceRegion,
userId: session?.factors?.user?.id, userId: session?.factors?.user?.id,
}); });
@@ -338,6 +352,7 @@ export async function sendVerificationRedirectWithoutCheck(
} else if ("userId" in command) { } else if ("userId" in command) {
const userResponse = await getUserByID({ const userResponse = await getUserByID({
serviceUrl, serviceUrl,
serviceRegion,
userId: command.userId, userId: command.userId,
}); });
@@ -377,6 +392,7 @@ export async function sendVerificationRedirectWithoutCheck(
const authMethodResponse = await listAuthenticationMethodTypes({ const authMethodResponse = await listAuthenticationMethodTypes({
serviceUrl, serviceUrl,
serviceRegion,
userId: user.userId, userId: user.userId,
}); });
@@ -402,6 +418,7 @@ export async function sendVerificationRedirectWithoutCheck(
const loginSettings = await getLoginSettings({ const loginSettings = await getLoginSettings({
serviceUrl, serviceUrl,
serviceRegion,
organization: user.details?.resourceOwner, organization: user.details?.resourceOwner,
}); });

View File

@@ -20,16 +20,17 @@ type ServiceClass =
export async function createServiceForHost<T extends ServiceClass>( export async function createServiceForHost<T extends ServiceClass>(
service: T, service: T,
serviceUrl: string, serviceUrl: string,
serviceRegion: string,
) { ) {
let token; let token;
// if we are running in a multitenancy context, use the system user token // if we are running in a multitenancy context, use the system user token
if ( if (
process.env.AUDIENCE && process.env[serviceRegion + "_AUDIENCE"] &&
process.env.SYSTEM_USER_ID && process.env[serviceRegion + "_SYSTEM_USER_ID"] &&
process.env.SYSTEM_USER_PRIVATE_KEY process.env[serviceRegion + "_SYSTEM_USER_PRIVATE_KEY"]
) { ) {
token = await systemAPIToken(); token = await systemAPIToken({ serviceRegion });
} else if (process.env.ZITADEL_SERVICE_USER_TOKEN) { } else if (process.env.ZITADEL_SERVICE_USER_TOKEN) {
token = process.env.ZITADEL_SERVICE_USER_TOKEN; token = process.env.ZITADEL_SERVICE_USER_TOKEN;
} }
@@ -49,7 +50,10 @@ export async function createServiceForHost<T extends ServiceClass>(
return createClientFor<T>(service)(transport); return createClientFor<T>(service)(transport);
} }
export function getServiceUrlFromHeaders(headers: ReadonlyHeaders): string { export function getServiceUrlFromHeaders(headers: ReadonlyHeaders): {
serviceUrl: string;
serviceRegion: string;
} {
let instanceUrl: string = process.env.ZITADEL_API_URL; let instanceUrl: string = process.env.ZITADEL_API_URL;
const forwardedHost = headers.get("x-zitadel-forward-host"); const forwardedHost = headers.get("x-zitadel-forward-host");
@@ -70,5 +74,8 @@ export function getServiceUrlFromHeaders(headers: ReadonlyHeaders): string {
} }
} }
return instanceUrl; return {
serviceUrl: instanceUrl,
serviceRegion: headers.get("x-zitadel-region") || "",
};
} }

View File

@@ -5,6 +5,7 @@ import { getSession } from "./zitadel";
type LoadMostRecentSessionParams = { type LoadMostRecentSessionParams = {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
sessionParams: { sessionParams: {
loginName?: string; loginName?: string;
organization?: string; organization?: string;
@@ -13,6 +14,7 @@ type LoadMostRecentSessionParams = {
export async function loadMostRecentSession({ export async function loadMostRecentSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionParams, sessionParams,
}: LoadMostRecentSessionParams): Promise<Session | undefined> { }: LoadMostRecentSessionParams): Promise<Session | undefined> {
const recent = await getMostRecentCookieWithLoginname({ const recent = await getMostRecentCookieWithLoginname({
@@ -22,6 +24,7 @@ export async function loadMostRecentSession({
return getSession({ return getSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionId: recent.id, sessionId: recent.id,
sessionToken: recent.token, sessionToken: recent.token,
}).then((resp: GetSessionResponse) => resp.session); }).then((resp: GetSessionResponse) => resp.session);

View File

@@ -55,13 +55,15 @@ async function cacheWrapper<T>(callback: Promise<T>) {
export async function getBrandingSettings({ export async function getBrandingSettings({
serviceUrl, serviceUrl,
serviceRegion,
organization, organization,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
organization?: string; organization?: string;
}) { }) {
const settingsService: Client<typeof SettingsService> = const settingsService: Client<typeof SettingsService> =
await createServiceForHost(SettingsService, serviceUrl); await createServiceForHost(SettingsService, serviceUrl, serviceRegion);
const callback = settingsService const callback = settingsService
.getBrandingSettings({ ctx: makeReqCtx(organization) }, {}) .getBrandingSettings({ ctx: makeReqCtx(organization) }, {})
@@ -72,13 +74,15 @@ export async function getBrandingSettings({
export async function getLoginSettings({ export async function getLoginSettings({
serviceUrl, serviceUrl,
serviceRegion,
organization, organization,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
organization?: string; organization?: string;
}) { }) {
const settingsService: Client<typeof SettingsService> = const settingsService: Client<typeof SettingsService> =
await createServiceForHost(SettingsService, serviceUrl); await createServiceForHost(SettingsService, serviceUrl, serviceRegion);
const callback = settingsService const callback = settingsService
.getLoginSettings({ ctx: makeReqCtx(organization) }, {}) .getLoginSettings({ ctx: makeReqCtx(organization) }, {})
@@ -89,14 +93,17 @@ export async function getLoginSettings({
export async function listIDPLinks({ export async function listIDPLinks({
serviceUrl, serviceUrl,
serviceRegion,
userId, userId,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
userId: string; userId: string;
}) { }) {
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.listIDPLinks({ userId }, {}); return userService.listIDPLinks({ userId }, {});
@@ -104,14 +111,17 @@ export async function listIDPLinks({
export async function addOTPEmail({ export async function addOTPEmail({
serviceUrl, serviceUrl,
serviceRegion,
userId, userId,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
userId: string; userId: string;
}) { }) {
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.addOTPEmail({ userId }, {}); return userService.addOTPEmail({ userId }, {});
@@ -119,14 +129,17 @@ export async function addOTPEmail({
export async function addOTPSMS({ export async function addOTPSMS({
serviceUrl, serviceUrl,
serviceRegion,
userId, userId,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
userId: string; userId: string;
}) { }) {
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.addOTPSMS({ userId }, {}); return userService.addOTPSMS({ userId }, {});
@@ -134,14 +147,17 @@ export async function addOTPSMS({
export async function registerTOTP({ export async function registerTOTP({
serviceUrl, serviceUrl,
serviceRegion,
userId, userId,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
userId: string; userId: string;
}) { }) {
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.registerTOTP({ userId }, {}); return userService.registerTOTP({ userId }, {});
@@ -149,11 +165,13 @@ export async function registerTOTP({
export async function getGeneralSettings({ export async function getGeneralSettings({
serviceUrl, serviceUrl,
serviceRegion,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
}) { }) {
const settingsService: Client<typeof SettingsService> = const settingsService: Client<typeof SettingsService> =
await createServiceForHost(SettingsService, serviceUrl); await createServiceForHost(SettingsService, serviceUrl, serviceRegion);
const callback = settingsService const callback = settingsService
.getGeneralSettings({}, {}) .getGeneralSettings({}, {})
@@ -164,13 +182,15 @@ export async function getGeneralSettings({
export async function getLegalAndSupportSettings({ export async function getLegalAndSupportSettings({
serviceUrl, serviceUrl,
serviceRegion,
organization, organization,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
organization?: string; organization?: string;
}) { }) {
const settingsService: Client<typeof SettingsService> = const settingsService: Client<typeof SettingsService> =
await createServiceForHost(SettingsService, serviceUrl); await createServiceForHost(SettingsService, serviceUrl, serviceRegion);
const callback = settingsService const callback = settingsService
.getLegalAndSupportSettings({ ctx: makeReqCtx(organization) }, {}) .getLegalAndSupportSettings({ ctx: makeReqCtx(organization) }, {})
@@ -181,13 +201,15 @@ export async function getLegalAndSupportSettings({
export async function getPasswordComplexitySettings({ export async function getPasswordComplexitySettings({
serviceUrl, serviceUrl,
serviceRegion,
organization, organization,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
organization?: string; organization?: string;
}) { }) {
const settingsService: Client<typeof SettingsService> = const settingsService: Client<typeof SettingsService> =
await createServiceForHost(SettingsService, serviceUrl); await createServiceForHost(SettingsService, serviceUrl, serviceRegion);
const callback = settingsService const callback = settingsService
.getPasswordComplexitySettings({ ctx: makeReqCtx(organization) }) .getPasswordComplexitySettings({ ctx: makeReqCtx(organization) })
@@ -198,28 +220,32 @@ export async function getPasswordComplexitySettings({
export async function createSessionFromChecks({ export async function createSessionFromChecks({
serviceUrl, serviceUrl,
serviceRegion,
checks, checks,
challenges, challenges,
lifetime, lifetime,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
checks: Checks; checks: Checks;
challenges: RequestChallenges | undefined; challenges: RequestChallenges | undefined;
lifetime?: Duration; lifetime?: Duration;
}) { }) {
const sessionService: Client<typeof SessionService> = const sessionService: Client<typeof SessionService> =
await createServiceForHost(SessionService, serviceUrl); await createServiceForHost(SessionService, serviceUrl, serviceRegion);
return sessionService.createSession({ checks, challenges, lifetime }, {}); return sessionService.createSession({ checks, challenges, lifetime }, {});
} }
export async function createSessionForUserIdAndIdpIntent({ export async function createSessionForUserIdAndIdpIntent({
serviceUrl, serviceUrl,
serviceRegion,
userId, userId,
idpIntent, idpIntent,
lifetime, lifetime,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
userId: string; userId: string;
idpIntent: { idpIntent: {
idpIntentId?: string | undefined; idpIntentId?: string | undefined;
@@ -228,7 +254,7 @@ export async function createSessionForUserIdAndIdpIntent({
lifetime?: Duration; lifetime?: Duration;
}) { }) {
const sessionService: Client<typeof SessionService> = const sessionService: Client<typeof SessionService> =
await createServiceForHost(SessionService, serviceUrl); await createServiceForHost(SessionService, serviceUrl, serviceRegion);
return sessionService.createSession({ return sessionService.createSession({
checks: { checks: {
@@ -246,6 +272,7 @@ export async function createSessionForUserIdAndIdpIntent({
export async function setSession({ export async function setSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionId, sessionId,
sessionToken, sessionToken,
challenges, challenges,
@@ -253,6 +280,7 @@ export async function setSession({
lifetime, lifetime,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
sessionId: string; sessionId: string;
sessionToken: string; sessionToken: string;
challenges: RequestChallenges | undefined; challenges: RequestChallenges | undefined;
@@ -260,7 +288,7 @@ export async function setSession({
lifetime?: Duration; lifetime?: Duration;
}) { }) {
const sessionService: Client<typeof SessionService> = const sessionService: Client<typeof SessionService> =
await createServiceForHost(SessionService, serviceUrl); await createServiceForHost(SessionService, serviceUrl, serviceRegion);
return sessionService.setSession( return sessionService.setSession(
{ {
@@ -277,42 +305,51 @@ export async function setSession({
export async function getSession({ export async function getSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionId, sessionId,
sessionToken, sessionToken,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
sessionId: string; sessionId: string;
sessionToken: string; sessionToken: string;
}) { }) {
const sessionService: Client<typeof SessionService> = const sessionService: Client<typeof SessionService> =
await createServiceForHost(SessionService, serviceUrl); await createServiceForHost(SessionService, serviceUrl, serviceRegion);
return sessionService.getSession({ sessionId, sessionToken }, {}); return sessionService.getSession({ sessionId, sessionToken }, {});
} }
export async function deleteSession({ export async function deleteSession({
serviceUrl, serviceUrl,
serviceRegion,
sessionId, sessionId,
sessionToken, sessionToken,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
sessionId: string; sessionId: string;
sessionToken: string; sessionToken: string;
}) { }) {
const sessionService: Client<typeof SessionService> = const sessionService: Client<typeof SessionService> =
await createServiceForHost(SessionService, serviceUrl); await createServiceForHost(SessionService, serviceUrl, serviceRegion);
return sessionService.deleteSession({ sessionId, sessionToken }, {}); return sessionService.deleteSession({ sessionId, sessionToken }, {});
} }
type ListSessionsCommand = { type ListSessionsCommand = {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
ids: string[]; ids: string[];
}; };
export async function listSessions({ serviceUrl, ids }: ListSessionsCommand) { export async function listSessions({
serviceUrl,
serviceRegion,
ids,
}: ListSessionsCommand) {
const sessionService: Client<typeof SessionService> = const sessionService: Client<typeof SessionService> =
await createServiceForHost(SessionService, serviceUrl); await createServiceForHost(SessionService, serviceUrl, serviceRegion);
return sessionService.listSessions( return sessionService.listSessions(
{ {
@@ -331,6 +368,7 @@ export async function listSessions({ serviceUrl, ids }: ListSessionsCommand) {
export type AddHumanUserData = { export type AddHumanUserData = {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
firstName: string; firstName: string;
lastName: string; lastName: string;
email: string; email: string;
@@ -340,6 +378,7 @@ export type AddHumanUserData = {
export async function addHumanUser({ export async function addHumanUser({
serviceUrl, serviceUrl,
serviceRegion,
email, email,
firstName, firstName,
lastName, lastName,
@@ -349,6 +388,7 @@ export async function addHumanUser({
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.addHumanUser({ return userService.addHumanUser({
@@ -372,14 +412,17 @@ export async function addHumanUser({
export async function addHuman({ export async function addHuman({
serviceUrl, serviceUrl,
serviceRegion,
request, request,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
request: AddHumanUserRequest; request: AddHumanUserRequest;
}) { }) {
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.addHumanUser(request); return userService.addHumanUser(request);
@@ -387,16 +430,19 @@ export async function addHuman({
export async function verifyTOTPRegistration({ export async function verifyTOTPRegistration({
serviceUrl, serviceUrl,
serviceRegion,
code, code,
userId, userId,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
code: string; code: string;
userId: string; userId: string;
}) { }) {
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.verifyTOTPRegistration({ code, userId }, {}); return userService.verifyTOTPRegistration({ code, userId }, {});
@@ -404,14 +450,17 @@ export async function verifyTOTPRegistration({
export async function getUserByID({ export async function getUserByID({
serviceUrl, serviceUrl,
serviceRegion,
userId, userId,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
userId: string; userId: string;
}) { }) {
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.getUserByID({ userId }, {}); return userService.getUserByID({ userId }, {});
@@ -419,16 +468,19 @@ export async function getUserByID({
export async function verifyInviteCode({ export async function verifyInviteCode({
serviceUrl, serviceUrl,
serviceRegion,
userId, userId,
verificationCode, verificationCode,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
userId: string; userId: string;
verificationCode: string; verificationCode: string;
}) { }) {
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.verifyInviteCode({ userId, verificationCode }, {}); return userService.verifyInviteCode({ userId, verificationCode }, {});
@@ -436,14 +488,17 @@ export async function verifyInviteCode({
export async function resendInviteCode({ export async function resendInviteCode({
serviceUrl, serviceUrl,
serviceRegion,
userId, userId,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
userId: string; userId: string;
}) { }) {
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.resendInviteCode({ userId }, {}); return userService.resendInviteCode({ userId }, {});
@@ -451,10 +506,12 @@ export async function resendInviteCode({
export async function sendEmailCode({ export async function sendEmailCode({
serviceUrl, serviceUrl,
serviceRegion,
userId, userId,
urlTemplate, urlTemplate,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
userId: string; userId: string;
urlTemplate: string; urlTemplate: string;
}) { }) {
@@ -473,6 +530,7 @@ export async function sendEmailCode({
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.sendEmailCode(medium, {}); return userService.sendEmailCode(medium, {});
@@ -480,10 +538,12 @@ export async function sendEmailCode({
export async function createInviteCode({ export async function createInviteCode({
serviceUrl, serviceUrl,
serviceRegion,
urlTemplate, urlTemplate,
userId, userId,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
urlTemplate: string; urlTemplate: string;
userId: string; userId: string;
}) { }) {
@@ -499,6 +559,7 @@ export async function createInviteCode({
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.createInviteCode( return userService.createInviteCode(
@@ -515,6 +576,7 @@ export async function createInviteCode({
export type ListUsersCommand = { export type ListUsersCommand = {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
loginName?: string; loginName?: string;
userName?: string; userName?: string;
email?: string; email?: string;
@@ -524,6 +586,7 @@ export type ListUsersCommand = {
export async function listUsers({ export async function listUsers({
serviceUrl, serviceUrl,
serviceRegion,
loginName, loginName,
userName, userName,
phone, phone,
@@ -615,6 +678,7 @@ export async function listUsers({
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.listUsers({ queries }); return userService.listUsers({ queries });
@@ -622,6 +686,7 @@ export async function listUsers({
export type SearchUsersCommand = { export type SearchUsersCommand = {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
searchValue: string; searchValue: string;
loginSettings: LoginSettings; loginSettings: LoginSettings;
organizationId?: string; organizationId?: string;
@@ -667,6 +732,7 @@ const EmailQuery = (searchValue: string) =>
* */ * */
export async function searchUsers({ export async function searchUsers({
serviceUrl, serviceUrl,
serviceRegion,
searchValue, searchValue,
loginSettings, loginSettings,
organizationId, organizationId,
@@ -700,6 +766,7 @@ export async function searchUsers({
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
const loginNameResult = await userService.listUsers({ queries }); const loginNameResult = await userService.listUsers({ queries });
@@ -786,11 +853,13 @@ export async function searchUsers({
export async function getDefaultOrg({ export async function getDefaultOrg({
serviceUrl, serviceUrl,
serviceRegion,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
}): Promise<Organization | null> { }): Promise<Organization | null> {
const orgService: Client<typeof OrganizationService> = const orgService: Client<typeof OrganizationService> =
await createServiceForHost(OrganizationService, serviceUrl); await createServiceForHost(OrganizationService, serviceUrl, serviceRegion);
return orgService return orgService
.listOrganizations( .listOrganizations(
@@ -811,13 +880,15 @@ export async function getDefaultOrg({
export async function getOrgsByDomain({ export async function getOrgsByDomain({
serviceUrl, serviceUrl,
serviceRegion,
domain, domain,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
domain: string; domain: string;
}) { }) {
const orgService: Client<typeof OrganizationService> = const orgService: Client<typeof OrganizationService> =
await createServiceForHost(OrganizationService, serviceUrl); await createServiceForHost(OrganizationService, serviceUrl, serviceRegion);
return orgService.listOrganizations( return orgService.listOrganizations(
{ {
@@ -836,16 +907,19 @@ export async function getOrgsByDomain({
export async function startIdentityProviderFlow({ export async function startIdentityProviderFlow({
serviceUrl, serviceUrl,
serviceRegion,
idpId, idpId,
urls, urls,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
idpId: string; idpId: string;
urls: RedirectURLsJson; urls: RedirectURLsJson;
}) { }) {
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.startIdentityProviderIntent({ return userService.startIdentityProviderIntent({
@@ -859,16 +933,19 @@ export async function startIdentityProviderFlow({
export async function retrieveIdentityProviderInformation({ export async function retrieveIdentityProviderInformation({
serviceUrl, serviceUrl,
serviceRegion,
idpIntentId, idpIntentId,
idpIntentToken, idpIntentToken,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
idpIntentId: string; idpIntentId: string;
idpIntentToken: string; idpIntentToken: string;
}) { }) {
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.retrieveIdentityProviderIntent({ return userService.retrieveIdentityProviderIntent({
@@ -879,12 +956,18 @@ export async function retrieveIdentityProviderInformation({
export async function getAuthRequest({ export async function getAuthRequest({
serviceUrl, serviceUrl,
serviceRegion,
authRequestId, authRequestId,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
authRequestId: string; authRequestId: string;
}) { }) {
const oidcService = await createServiceForHost(OIDCService, serviceUrl); const oidcService = await createServiceForHost(
OIDCService,
serviceUrl,
serviceRegion,
);
return oidcService.getAuthRequest({ return oidcService.getAuthRequest({
authRequestId, authRequestId,
@@ -893,28 +976,37 @@ export async function getAuthRequest({
export async function createCallback({ export async function createCallback({
serviceUrl, serviceUrl,
serviceRegion,
req, req,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
req: CreateCallbackRequest; req: CreateCallbackRequest;
}) { }) {
const oidcService = await createServiceForHost(OIDCService, serviceUrl); const oidcService = await createServiceForHost(
OIDCService,
serviceUrl,
serviceRegion,
);
return oidcService.createCallback(req); return oidcService.createCallback(req);
} }
export async function verifyEmail({ export async function verifyEmail({
serviceUrl, serviceUrl,
serviceRegion,
userId, userId,
verificationCode, verificationCode,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
userId: string; userId: string;
verificationCode: string; verificationCode: string;
}) { }) {
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.verifyEmail( return userService.verifyEmail(
@@ -928,10 +1020,12 @@ export async function verifyEmail({
export async function resendEmailCode({ export async function resendEmailCode({
serviceUrl, serviceUrl,
serviceRegion,
userId, userId,
urlTemplate, urlTemplate,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
userId: string; userId: string;
urlTemplate: string; urlTemplate: string;
}) { }) {
@@ -948,6 +1042,7 @@ export async function resendEmailCode({
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.resendEmailCode(request, {}); return userService.resendEmailCode(request, {});
@@ -955,16 +1050,19 @@ export async function resendEmailCode({
export async function retrieveIDPIntent({ export async function retrieveIDPIntent({
serviceUrl, serviceUrl,
serviceRegion,
id, id,
token, token,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
id: string; id: string;
token: string; token: string;
}) { }) {
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.retrieveIdentityProviderIntent( return userService.retrieveIdentityProviderIntent(
@@ -975,29 +1073,38 @@ export async function retrieveIDPIntent({
export async function getIDPByID({ export async function getIDPByID({
serviceUrl, serviceUrl,
serviceRegion,
id, id,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
id: string; id: string;
}) { }) {
const idpService: Client<typeof IdentityProviderService> = const idpService: Client<typeof IdentityProviderService> =
await createServiceForHost(IdentityProviderService, serviceUrl); await createServiceForHost(
IdentityProviderService,
serviceUrl,
serviceRegion,
);
return idpService.getIDPByID({ id }, {}).then((resp) => resp.idp); return idpService.getIDPByID({ id }, {}).then((resp) => resp.idp);
} }
export async function addIDPLink({ export async function addIDPLink({
serviceUrl, serviceUrl,
serviceRegion,
idp, idp,
userId, userId,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
idp: { id: string; userId: string; userName: string }; idp: { id: string; userId: string; userName: string };
userId: string; userId: string;
}) { }) {
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.addIDPLink( return userService.addIDPLink(
@@ -1015,10 +1122,12 @@ export async function addIDPLink({
export async function passwordReset({ export async function passwordReset({
serviceUrl, serviceUrl,
serviceRegion,
userId, userId,
urlTemplate, urlTemplate,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
userId: string; userId: string;
urlTemplate?: string; urlTemplate?: string;
}) { }) {
@@ -1034,6 +1143,7 @@ export async function passwordReset({
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.passwordReset( return userService.passwordReset(
@@ -1050,12 +1160,14 @@ export async function passwordReset({
export async function setUserPassword({ export async function setUserPassword({
serviceUrl, serviceUrl,
serviceRegion,
userId, userId,
password, password,
user, user,
code, code,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
userId: string; userId: string;
password: string; password: string;
user: User; user: User;
@@ -1072,6 +1184,7 @@ export async function setUserPassword({
if (!code) { if (!code) {
const authmethods = await listAuthenticationMethodTypes({ const authmethods = await listAuthenticationMethodTypes({
serviceUrl, serviceUrl,
serviceRegion,
userId, userId,
}); });
@@ -1097,6 +1210,7 @@ export async function setUserPassword({
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.setPassword(payload, {}).catch((error) => { return userService.setPassword(payload, {}).catch((error) => {
@@ -1111,14 +1225,17 @@ export async function setUserPassword({
export async function setPassword({ export async function setPassword({
serviceUrl, serviceUrl,
serviceRegion,
payload, payload,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
payload: SetPasswordRequest; payload: SetPasswordRequest;
}) { }) {
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.setPassword(payload, {}); return userService.setPassword(payload, {});
@@ -1132,14 +1249,17 @@ export async function setPassword({
*/ */
export async function createPasskeyRegistrationLink({ export async function createPasskeyRegistrationLink({
serviceUrl, serviceUrl,
serviceRegion,
userId, userId,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
userId: string; userId: string;
}) { }) {
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.createPasskeyRegistrationLink({ return userService.createPasskeyRegistrationLink({
@@ -1160,16 +1280,19 @@ export async function createPasskeyRegistrationLink({
*/ */
export async function registerU2F({ export async function registerU2F({
serviceUrl, serviceUrl,
serviceRegion,
userId, userId,
domain, domain,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
userId: string; userId: string;
domain: string; domain: string;
}) { }) {
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.registerU2F({ return userService.registerU2F({
@@ -1186,14 +1309,17 @@ export async function registerU2F({
*/ */
export async function verifyU2FRegistration({ export async function verifyU2FRegistration({
serviceUrl, serviceUrl,
serviceRegion,
request, request,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
request: VerifyU2FRegistrationRequest; request: VerifyU2FRegistrationRequest;
}) { }) {
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.verifyU2FRegistration(request, {}); return userService.verifyU2FRegistration(request, {});
@@ -1208,10 +1334,12 @@ export async function verifyU2FRegistration({
*/ */
export async function getActiveIdentityProviders({ export async function getActiveIdentityProviders({
serviceUrl, serviceUrl,
serviceRegion,
orgId, orgId,
linking_allowed, linking_allowed,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
orgId?: string; orgId?: string;
linking_allowed?: boolean; linking_allowed?: boolean;
}) { }) {
@@ -1220,7 +1348,7 @@ export async function getActiveIdentityProviders({
props.linkingAllowed = linking_allowed; props.linkingAllowed = linking_allowed;
} }
const settingsService: Client<typeof SettingsService> = const settingsService: Client<typeof SettingsService> =
await createServiceForHost(SettingsService, serviceUrl); await createServiceForHost(SettingsService, serviceUrl, serviceRegion);
return settingsService.getActiveIdentityProviders(props, {}); return settingsService.getActiveIdentityProviders(props, {});
} }
@@ -1233,14 +1361,17 @@ export async function getActiveIdentityProviders({
*/ */
export async function verifyPasskeyRegistration({ export async function verifyPasskeyRegistration({
serviceUrl, serviceUrl,
serviceRegion,
request, request,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
request: VerifyPasskeyRegistrationRequest; request: VerifyPasskeyRegistrationRequest;
}) { }) {
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.verifyPasskeyRegistration(request, {}); return userService.verifyPasskeyRegistration(request, {});
@@ -1256,11 +1387,13 @@ export async function verifyPasskeyRegistration({
*/ */
export async function registerPasskey({ export async function registerPasskey({
serviceUrl, serviceUrl,
serviceRegion,
userId, userId,
code, code,
domain, domain,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
userId: string; userId: string;
code: { id: string; code: string }; code: { id: string; code: string };
domain: string; domain: string;
@@ -1268,6 +1401,7 @@ export async function registerPasskey({
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.registerPasskey({ return userService.registerPasskey({
@@ -1285,14 +1419,17 @@ export async function registerPasskey({
*/ */
export async function listAuthenticationMethodTypes({ export async function listAuthenticationMethodTypes({
serviceUrl, serviceUrl,
serviceRegion,
userId, userId,
}: { }: {
serviceUrl: string; serviceUrl: string;
serviceRegion: string;
userId: string; userId: string;
}) { }) {
const userService: Client<typeof UserService> = await createServiceForHost( const userService: Client<typeof UserService> = await createServiceForHost(
UserService, UserService,
serviceUrl, serviceUrl,
serviceRegion,
); );
return userService.listAuthenticationMethodTypes({ return userService.listAuthenticationMethodTypes({

View File

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

View File

@@ -6,6 +6,12 @@
"DEBUG", "DEBUG",
"VERCEL_URL", "VERCEL_URL",
"EMAIL_VERIFICATION", "EMAIL_VERIFICATION",
"EU1_AUDIENCE",
"EU1_SYSTEM_USER_ID",
"EU1_SYSTEM_USER_PRIVATE_KEY",
"US1_AUDIENCE",
"US1_SYSTEM_USER_ID",
"US1_SYSTEM_USER_PRIVATE_KEY",
"AUDIENCE", "AUDIENCE",
"SYSTEM_USER_ID", "SYSTEM_USER_ID",
"SYSTEM_USER_PRIVATE_KEY", "SYSTEM_USER_PRIVATE_KEY",