cleanup serviceUrl, host, basepath configurable

This commit is contained in:
Max Peintner
2025-01-29 10:34:33 +01:00
parent e8900501b9
commit 04f9b47960
43 changed files with 426 additions and 597 deletions

View File

@@ -35,7 +35,7 @@ const secureHeaders = [
];
const nextConfig = {
basePath: "/new-login",
basePath: process.env.NEXT_PUBLIC_BASE_PATH,
reactStrictMode: true, // Recommended for the `pages` directory, default in `app`.
experimental: {
dynamicIO: true,

View File

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

View File

@@ -30,16 +30,11 @@ export default async function Page(props: {
const { loginName, authRequestId, organization, sessionId } = searchParams;
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
const sessionWithData = sessionId
? await loadSessionById(host, sessionId, organization)
: await loadSessionByLoginname(host, loginName, organization);
? await loadSessionById(serviceUrl, sessionId, organization)
: await loadSessionByLoginname(serviceUrl, loginName, organization);
async function getAuthMethodsAndUser(host: string, session?: Session) {
const userId = session?.factors?.user?.id;
@@ -48,20 +43,24 @@ export default async function Page(props: {
throw Error("Could not get user id from session");
}
return listAuthenticationMethodTypes({ host, userId }).then((methods) => {
return getUserByID({ host, userId }).then((user) => {
const humanUser =
user.user?.type.case === "human" ? user.user?.type.value : undefined;
return listAuthenticationMethodTypes({ serviceUrl, userId }).then(
(methods) => {
return getUserByID({ serviceUrl, userId }).then((user) => {
const humanUser =
user.user?.type.case === "human"
? user.user?.type.value
: undefined;
return {
factors: session?.factors,
authMethods: methods.authMethodTypes ?? [],
phoneVerified: humanUser?.phone?.isVerified ?? false,
emailVerified: humanUser?.email?.isVerified ?? false,
expirationDate: session?.expirationDate,
};
});
});
return {
factors: session?.factors,
authMethods: methods.authMethodTypes ?? [],
phoneVerified: humanUser?.phone?.isVerified ?? false,
emailVerified: humanUser?.email?.isVerified ?? false,
expirationDate: session?.expirationDate,
};
});
},
);
}
async function loadSessionByLoginname(
@@ -70,13 +69,13 @@ export default async function Page(props: {
organization?: string,
) {
return loadMostRecentSession({
host,
serviceUrl,
sessionParams: {
loginName,
organization,
},
}).then((session) => {
return getAuthMethodsAndUser(host, session);
return getAuthMethodsAndUser(serviceUrl, session);
});
}
@@ -87,11 +86,11 @@ export default async function Page(props: {
) {
const recent = await getSessionCookieById({ sessionId, organization });
return getSession({
host,
serviceUrl,
sessionId: recent.id,
sessionToken: recent.token,
}).then((sessionResponse) => {
return getAuthMethodsAndUser(host, sessionResponse.session);
return getAuthMethodsAndUser(serviceUrl, sessionResponse.session);
});
}
@@ -100,17 +99,17 @@ export default async function Page(props: {
}
const branding = await getBrandingSettings({
host,
serviceUrl,
organization: sessionWithData.factors?.user?.organizationId,
});
const loginSettings = await getLoginSettings({
host,
serviceUrl,
organization: sessionWithData.factors?.user?.organizationId,
});
const identityProviders = await getActiveIdentityProviders({
host,
serviceUrl,
orgId: sessionWithData.factors?.user?.organizationId,
linking_allowed: true,
}).then((resp) => {

View File

@@ -25,14 +25,9 @@ export default async function Page(props: {
const { organization } = searchParams;
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
const serviceUrl = getApiUrlOfHeaders(_headers);
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const branding = await getBrandingSettings({ host, organization });
const branding = await getBrandingSettings({ serviceUrl, organization });
return (
<DynamicTheme branding={branding}>

View File

@@ -40,21 +40,16 @@ export default async function Page(props: {
const { provider } = params;
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
const serviceUrl = getApiUrlOfHeaders(_headers);
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const branding = await getBrandingSettings({ host, organization });
const branding = await getBrandingSettings({ serviceUrl, organization });
if (!provider || !id || !token) {
return loginFailed(branding, "IDP context missing");
}
const intent = await retrieveIDPIntent({
serviceUrl: instanceUrl,
serviceUrl,
id,
token,
});
@@ -77,7 +72,7 @@ export default async function Page(props: {
return loginFailed(branding, "IDP information missing");
}
const idp = await getIDPByID({ host, id: idpInformation.idpId });
const idp = await getIDPByID({ serviceUrl, id: idpInformation.idpId });
const options = idp?.config?.options;
if (!idp) {
@@ -95,7 +90,7 @@ export default async function Page(props: {
let idpLink;
try {
idpLink = await addIDPLink({
host,
serviceUrl,
idp: {
id: idpInformation.idpId,
userId: idpInformation.userId,
@@ -126,20 +121,20 @@ export default async function Page(props: {
const email = PROVIDER_MAPPING[providerType](idpInformation).email?.email;
if (options.autoLinking === AutoLinkingOption.EMAIL && email) {
foundUser = await listUsers({ host, email }).then((response) => {
foundUser = await listUsers({ serviceUrl, email }).then((response) => {
return response.result ? response.result[0] : null;
});
} else if (options.autoLinking === AutoLinkingOption.USERNAME) {
foundUser = await listUsers(
options.autoLinking === AutoLinkingOption.USERNAME
? { host, userName: idpInformation.userName }
: { host, email },
? { serviceUrl, userName: idpInformation.userName }
: { serviceUrl, email },
).then((response) => {
return response.result ? response.result[0] : null;
});
} else {
foundUser = await listUsers({
host,
serviceUrl,
userName: idpInformation.userName,
email,
}).then((response) => {
@@ -151,7 +146,7 @@ export default async function Page(props: {
let idpLink;
try {
idpLink = await addIDPLink({
host,
serviceUrl,
idp: {
id: idpInformation.idpId,
userId: idpInformation.userId,
@@ -192,12 +187,12 @@ export default async function Page(props: {
const suffix = matched?.[1] ?? "";
// this just returns orgs where the suffix is set as primary domain
const orgs = await getOrgsByDomain({ host, domain: suffix });
const orgs = await getOrgsByDomain({ serviceUrl, domain: suffix });
const orgToCheckForDiscovery =
orgs.result && orgs.result.length === 1 ? orgs.result[0].id : undefined;
const orgLoginSettings = await getLoginSettings({
host,
serviceUrl,
organization: orgToCheckForDiscovery,
});
if (orgLoginSettings?.allowDomainDiscovery) {
@@ -216,7 +211,7 @@ export default async function Page(props: {
});
}
const newUser = await addHuman({ host, request: userData });
const newUser = await addHuman({ serviceUrl, request: userData });
if (newUser) {
return (

View File

@@ -16,21 +16,16 @@ export default async function Page(props: {
const organization = searchParams?.organization;
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
const identityProviders = await getActiveIdentityProviders({
host,
serviceUrl,
orgId: organization,
}).then((resp) => {
return resp.identityProviders;
});
const branding = await getBrandingSettings({ host, organization });
const branding = await getBrandingSettings({ serviceUrl, organization });
return (
<DynamicTheme branding={branding}>

View File

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

View File

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

View File

@@ -26,37 +26,35 @@ export default async function Page(props: {
const submit: boolean = searchParams?.submit === "true";
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
let defaultOrganization;
if (!organization) {
const org: Organization | null = await getDefaultOrg({ host });
const org: Organization | null = await getDefaultOrg({ serviceUrl });
if (org) {
defaultOrganization = org.id;
}
}
const loginSettings = await getLoginSettings({
host,
serviceUrl,
organization: organization ?? defaultOrganization,
});
const contextLoginSettings = await getLoginSettings({ host, organization });
const contextLoginSettings = await getLoginSettings({
serviceUrl,
organization,
});
const identityProviders = await getActiveIdentityProviders({
host,
serviceUrl,
orgId: organization ?? defaultOrganization,
}).then((resp) => {
return resp.identityProviders;
});
const branding = await getBrandingSettings({
host,
serviceUrl,
organization: organization ?? defaultOrganization,
});

View File

@@ -25,24 +25,19 @@ export default async function Page(props: {
const { loginName, authRequestId, organization, sessionId } = searchParams;
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
const sessionFactors = sessionId
? await loadSessionById(host, sessionId, organization)
: await loadSessionByLoginname(host, loginName, organization);
? await loadSessionById(serviceUrl, sessionId, organization)
: await loadSessionByLoginname(serviceUrl, loginName, organization);
async function loadSessionByLoginname(
host: string,
serviceUrl: string,
loginName?: string,
organization?: string,
) {
return loadMostRecentSession({
host,
serviceUrl,
sessionParams: {
loginName,
organization,
@@ -50,7 +45,7 @@ export default async function Page(props: {
}).then((session) => {
if (session && session.factors?.user?.id) {
return listAuthenticationMethodTypes({
host,
serviceUrl,
userId: session.factors.user.id,
}).then((methods) => {
return {
@@ -69,13 +64,13 @@ export default async function Page(props: {
) {
const recent = await getSessionCookieById({ sessionId, organization });
return getSession({
host,
serviceUrl,
sessionId: recent.id,
sessionToken: recent.token,
}).then((response) => {
if (response?.session && response.session.factors?.user?.id) {
return listAuthenticationMethodTypes({
host,
serviceUrl,
userId: response.session.factors.user.id,
}).then((methods) => {
return {
@@ -87,7 +82,7 @@ export default async function Page(props: {
});
}
const branding = await getBrandingSettings({ host, organization });
const branding = await getBrandingSettings({ serviceUrl, organization });
return (
<DynamicTheme branding={branding}>

View File

@@ -52,16 +52,11 @@ export default async function Page(props: {
} = searchParams;
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
const sessionWithData = sessionId
? await loadSessionById(host, sessionId, organization)
: await loadSessionByLoginname(host, loginName, organization);
? await loadSessionById(serviceUrl, sessionId, organization)
: await loadSessionByLoginname(serviceUrl, loginName, organization);
async function getAuthMethodsAndUser(host: string, session?: Session) {
const userId = session?.factors?.user?.id;
@@ -70,20 +65,24 @@ export default async function Page(props: {
throw Error("Could not get user id from session");
}
return listAuthenticationMethodTypes({ host, userId }).then((methods) => {
return getUserByID({ host, userId }).then((user) => {
const humanUser =
user.user?.type.case === "human" ? user.user?.type.value : undefined;
return listAuthenticationMethodTypes({ serviceUrl, userId }).then(
(methods) => {
return getUserByID({ serviceUrl, userId }).then((user) => {
const humanUser =
user.user?.type.case === "human"
? user.user?.type.value
: undefined;
return {
factors: session?.factors,
authMethods: methods.authMethodTypes ?? [],
phoneVerified: humanUser?.phone?.isVerified ?? false,
emailVerified: humanUser?.email?.isVerified ?? false,
expirationDate: session?.expirationDate,
};
});
});
return {
factors: session?.factors,
authMethods: methods.authMethodTypes ?? [],
phoneVerified: humanUser?.phone?.isVerified ?? false,
emailVerified: humanUser?.email?.isVerified ?? false,
expirationDate: session?.expirationDate,
};
});
},
);
}
async function loadSessionByLoginname(
@@ -92,13 +91,13 @@ export default async function Page(props: {
organization?: string,
) {
return loadMostRecentSession({
host,
serviceUrl,
sessionParams: {
loginName,
organization,
},
}).then((session) => {
return getAuthMethodsAndUser(host, session);
return getAuthMethodsAndUser(serviceUrl, session);
});
}
@@ -109,17 +108,17 @@ export default async function Page(props: {
) {
const recent = await getSessionCookieById({ sessionId, organization });
return getSession({
host,
serviceUrl,
sessionId: recent.id,
sessionToken: recent.token,
}).then((sessionResponse) => {
return getAuthMethodsAndUser(host, sessionResponse.session);
return getAuthMethodsAndUser(serviceUrl, sessionResponse.session);
});
}
const branding = await getBrandingSettings({ host, organization });
const branding = await getBrandingSettings({ serviceUrl, organization });
const loginSettings = await getLoginSettings({
host,
serviceUrl,
organization: sessionWithData.factors?.user?.organizationId,
});

View File

@@ -24,17 +24,13 @@ export default async function Page(props: {
const tError = await getTranslations({ locale, namespace: "error" });
const _headers = await headers();
const serviceUrl = getApiUrlOfHeaders(_headers);
const host = _headers.get("host");
const instanceUrl = getApiUrlOfHeaders(_headers);
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
if (!instanceUrl) {
throw new Error("No instanceUrl found");
}
const {
loginName, // send from password page
userId, // send from email link
@@ -48,9 +44,9 @@ export default async function Page(props: {
const { method } = params;
const session = sessionId
? await loadSessionById(instanceUrl, sessionId, organization)
? await loadSessionById(serviceUrl, sessionId, organization)
: await loadMostRecentSession({
host: instanceUrl,
serviceUrl,
sessionParams: { loginName, organization },
});
@@ -61,7 +57,7 @@ export default async function Page(props: {
) {
const recent = await getSessionCookieById({ sessionId, organization });
return getSession({
host,
serviceUrl,
sessionId: recent.id,
sessionToken: recent.token,
}).then((response) => {
@@ -73,12 +69,12 @@ export default async function Page(props: {
// email links do not come with organization, thus we need to use the session's organization
const branding = await getBrandingSettings({
host: instanceUrl,
serviceUrl,
organization: organization ?? session?.factors?.user?.organizationId,
});
const loginSettings = await getLoginSettings({
host: instanceUrl,
serviceUrl,
organization: organization ?? session?.factors?.user?.organizationId,
});

View File

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

View File

@@ -25,28 +25,23 @@ export default async function Page(props: {
searchParams;
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
const sessionFactors = sessionId
? await loadSessionById(host, sessionId, organization)
? await loadSessionById(serviceUrl, sessionId, organization)
: await loadMostRecentSession({
host,
serviceUrl,
sessionParams: { loginName, organization },
});
async function loadSessionById(
host: string,
serviceUrl: string,
sessionId: string,
organization?: string,
) {
const recent = await getSessionCookieById({ sessionId, organization });
return getSession({
host,
serviceUrl,
sessionId: recent.id,
sessionToken: recent.token,
}).then((response) => {
@@ -56,9 +51,9 @@ export default async function Page(props: {
});
}
const branding = await getBrandingSettings({ host, organization });
const branding = await getBrandingSettings({ serviceUrl, organization });
const loginSettings = await getLoginSettings({ host, organization });
const loginSettings = await getLoginSettings({ serviceUrl, organization });
return (
<DynamicTheme branding={branding}>

View File

@@ -20,22 +20,17 @@ export default async function Page(props: {
searchParams;
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
const session = await loadMostRecentSession({
host,
serviceUrl,
sessionParams: {
loginName,
organization,
},
});
const branding = await getBrandingSettings({ host, organization });
const branding = await getBrandingSettings({ serviceUrl, organization });
return (
<DynamicTheme branding={branding}>

View File

@@ -16,12 +16,7 @@ export default async function Page(props: {
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
}) {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
const searchParams = await props.searchParams;
const locale = getLocale();
@@ -32,22 +27,22 @@ export default async function Page(props: {
// also allow no session to be found (ignoreUnkownUsername)
const sessionFactors = await loadMostRecentSession({
host,
serviceUrl,
sessionParams: {
loginName,
organization,
},
});
const branding = await getBrandingSettings({ host, organization });
const branding = await getBrandingSettings({ serviceUrl, organization });
const passwordComplexity = await getPasswordComplexitySettings({
host,
serviceUrl,
organization: sessionFactors?.factors?.user?.organizationId,
});
const loginSettings = await getLoginSettings({
host,
serviceUrl,
organization: sessionFactors?.factors?.user?.organizationId,
});

View File

@@ -25,16 +25,11 @@ export default async function Page(props: {
let { loginName, organization, authRequestId, alt } = searchParams;
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
let defaultOrganization;
if (!organization) {
const org: Organization | null = await getDefaultOrg({ host });
const org: Organization | null = await getDefaultOrg({ serviceUrl });
if (org) {
defaultOrganization = org.id;
@@ -45,7 +40,7 @@ export default async function Page(props: {
let sessionFactors;
try {
sessionFactors = await loadMostRecentSession({
host,
serviceUrl,
sessionParams: {
loginName,
organization,
@@ -57,11 +52,11 @@ export default async function Page(props: {
}
const branding = await getBrandingSettings({
host,
serviceUrl,
organization: organization ?? defaultOrganization,
});
const loginSettings = await getLoginSettings({
host,
serviceUrl,
organization: organization ?? defaultOrganization,
});

View File

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

View File

@@ -23,29 +23,24 @@ export default async function Page(props: {
searchParams;
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
if (!organization) {
const org: Organization | null = await getDefaultOrg({ host });
const org: Organization | null = await getDefaultOrg({ serviceUrl });
if (org) {
organization = org.id;
}
}
const legal = await getLegalAndSupportSettings({ host, organization });
const legal = await getLegalAndSupportSettings({ serviceUrl, organization });
const passwordComplexitySettings = await getPasswordComplexitySettings({
host,
serviceUrl,
organization,
});
const branding = await getBrandingSettings({ host, organization });
const branding = await getBrandingSettings({ serviceUrl, organization });
const loginSettings = await getLoginSettings({ host, organization });
const loginSettings = await getLoginSettings({ serviceUrl, organization });
if (!loginSettings?.allowRegister) {
return (

View File

@@ -23,15 +23,10 @@ export default async function Page(props: {
searchParams;
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
if (!organization) {
const org: Organization | null = await getDefaultOrg({ host });
const org: Organization | null = await getDefaultOrg({ serviceUrl });
if (org) {
organization = org.id;
}
@@ -39,15 +34,15 @@ export default async function Page(props: {
const missingData = !firstname || !lastname || !email;
const legal = await getLegalAndSupportSettings({ host, organization });
const legal = await getLegalAndSupportSettings({ serviceUrl, organization });
const passwordComplexitySettings = await getPasswordComplexitySettings({
host,
serviceUrl,
organization,
});
const branding = await getBrandingSettings({ host, organization });
const branding = await getBrandingSettings({ serviceUrl, organization });
const loginSettings = await getLoginSettings({ host, organization });
const loginSettings = await getLoginSettings({ serviceUrl, organization });
return missingData ? (
<DynamicTheme branding={branding}>

View File

@@ -21,7 +21,7 @@ import Link from "next/link";
import { redirect } from "next/navigation";
async function loadSession(
host: string,
serviceUrl: string,
loginName: string,
authRequestId?: string,
) {
@@ -29,7 +29,7 @@ async function loadSession(
if (authRequestId) {
return createCallback({
host,
serviceUrl,
req: create(CreateCallbackRequestSchema, {
authRequestId,
callbackKind: {
@@ -45,7 +45,7 @@ async function loadSession(
});
}
return getSession({
host,
serviceUrl,
sessionId: recent.id,
sessionToken: recent.token,
}).then((response) => {
@@ -61,21 +61,20 @@ export default async function Page(props: { searchParams: Promise<any> }) {
const t = await getTranslations({ locale, namespace: "signedin" });
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
const { loginName, authRequestId, organization } = searchParams;
const sessionFactors = await loadSession(host, loginName, authRequestId);
const sessionFactors = await loadSession(
serviceUrl,
loginName,
authRequestId,
);
const branding = await getBrandingSettings({ host, organization });
const branding = await getBrandingSettings({ serviceUrl, organization });
let loginSettings;
if (!authRequestId) {
loginSettings = await getLoginSettings({ host, organization });
loginSettings = await getLoginSettings({ serviceUrl, organization });
}
return (

View File

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

View File

@@ -19,22 +19,17 @@ export default async function Page(props: {
const { loginName, organization, authRequestId, checkAfter } = searchParams;
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
const sessionFactors = await loadMostRecentSession({
host,
serviceUrl,
sessionParams: {
loginName,
organization,
},
});
const branding = await getBrandingSettings({ host, organization });
const branding = await getBrandingSettings({ serviceUrl, organization });
return (
<DynamicTheme branding={branding}>

View File

@@ -26,7 +26,7 @@ export default async function Page(props: { searchParams: Promise<any> }) {
searchParams;
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const serviceUrl = getApiUrlOfHeaders(_headers);
const host = _headers.get("host");
if (!host || typeof host !== "string") {
@@ -34,7 +34,7 @@ export default async function Page(props: { searchParams: Promise<any> }) {
}
const branding = await getBrandingSettings({
host: instanceUrl,
serviceUrl,
organization,
});
@@ -47,7 +47,7 @@ export default async function Page(props: { searchParams: Promise<any> }) {
if ("loginName" in searchParams) {
sessionFactors = await loadMostRecentSession({
host: instanceUrl,
serviceUrl,
sessionParams: {
loginName,
organization,
@@ -56,12 +56,11 @@ export default async function Page(props: { searchParams: Promise<any> }) {
if (doSend && sessionFactors?.factors?.user?.id) {
await sendEmailCode({
host,
serviceUrl,
userId: sessionFactors?.factors?.user?.id,
urlTemplate:
`${host.includes("localhost") ? "http://" : "https://"}${host}/verify?code={{.Code}}&userId={{.UserID}}&organization={{.OrgID}}&invite=true` +
(authRequestId ? `&authRequestId=${authRequestId}` : ""),
userId: sessionFactors?.factors?.user?.id,
authRequestId,
}).catch((error) => {
console.error("Could not resend verification email", error);
throw Error("Failed to send verification email");
@@ -70,9 +69,11 @@ export default async function Page(props: { searchParams: Promise<any> }) {
} else if ("userId" in searchParams && userId) {
if (doSend) {
await sendEmailCode({
host,
serviceUrl,
userId,
authRequestId,
urlTemplate:
`${host.includes("localhost") ? "http://" : "https://"}${host}/verify?code={{.Code}}&userId={{.UserID}}&organization={{.OrgID}}&invite=true` +
(authRequestId ? `&authRequestId=${authRequestId}` : ""),
}).catch((error) => {
console.error("Could not resend verification email", error);
throw Error("Failed to send verification email");

View File

@@ -30,9 +30,15 @@ export const dynamic = "force-dynamic";
export const revalidate = false;
export const fetchCache = "default-no-store";
async function loadSessions(host: string, ids: string[]): Promise<Session[]> {
async function loadSessions({
serviceUrl,
ids,
}: {
serviceUrl: string;
ids: string[];
}): Promise<Session[]> {
const response = await listSessions({
host,
serviceUrl,
ids: ids.filter((id: string | undefined) => !!id),
});
@@ -48,7 +54,7 @@ const IDP_SCOPE_REGEX = /urn:zitadel:iam:org:idp:id:(.+)/;
* to check for mfa for automatically selected session -> const response = await listAuthenticationMethodTypes(userId);
**/
async function isSessionValid(
host: string,
serviceUrl: string,
session: Session,
): Promise<boolean> {
// session can't be checked without user
@@ -60,7 +66,7 @@ async function isSessionValid(
let mfaValid = true;
const authMethodTypes = await listAuthenticationMethodTypes({
host,
serviceUrl,
userId: session.factors.user.id,
});
@@ -109,7 +115,7 @@ async function isSessionValid(
} else {
// only check settings if no auth methods are available, as this would require a setup
const loginSettings = await getLoginSettings({
host,
serviceUrl,
organization: session.factors?.user?.organizationId,
});
if (loginSettings?.forceMfa || loginSettings?.forceMfaLocalOnly) {
@@ -152,7 +158,7 @@ async function isSessionValid(
}
async function findValidSession(
host: string,
serviceUrl: string,
sessions: Session[],
authRequest: AuthRequest,
): Promise<Session | undefined> {
@@ -179,7 +185,7 @@ async function findValidSession(
// return the first valid session according to settings
for (const session of sessionsWithHint) {
if (await isSessionValid(host, session)) {
if (await isSessionValid(serviceUrl, session)) {
return session;
}
}
@@ -193,12 +199,7 @@ export async function GET(request: NextRequest) {
const sessionId = searchParams.get("sessionId");
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
// 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");
@@ -210,7 +211,7 @@ export async function GET(request: NextRequest) {
const ids = sessionCookies.map((s) => s.id);
let sessions: Session[] = [];
if (ids && ids.length) {
sessions = await loadSessions(host, ids);
sessions = await loadSessions({ serviceUrl, ids });
}
if (authRequestId && sessionId) {
@@ -223,7 +224,7 @@ export async function GET(request: NextRequest) {
if (selectedSession && selectedSession.id) {
console.log(`Found session ${selectedSession.id}`);
const isValid = await isSessionValid(host, selectedSession);
const isValid = await isSessionValid(serviceUrl, selectedSession);
console.log("Session is valid:", isValid);
@@ -257,7 +258,7 @@ export async function GET(request: NextRequest) {
// works not with _rsc request
try {
const { callbackUrl } = await createCallback({
host,
serviceUrl,
req: create(CreateCallbackRequestSchema, {
authRequestId,
callbackKind: {
@@ -284,7 +285,7 @@ export async function GET(request: NextRequest) {
error?.code === 9
) {
const loginSettings = await getLoginSettings({
host,
serviceUrl,
organization: selectedSession.factors?.user?.organizationId,
});
@@ -316,7 +317,7 @@ export async function GET(request: NextRequest) {
}
if (authRequestId) {
const { authRequest } = await getAuthRequest({ host, authRequestId });
const { authRequest } = await getAuthRequest({ serviceUrl, authRequestId });
let organization = "";
let suffix = "";
@@ -343,7 +344,10 @@ export async function GET(request: NextRequest) {
const matched = ORG_DOMAIN_SCOPE_REGEX.exec(orgDomainScope);
const orgDomain = matched?.[1] ?? "";
if (orgDomain) {
const orgs = await getOrgsByDomain({ host, domain: orgDomain });
const orgs = await getOrgsByDomain({
serviceUrl,
domain: orgDomain,
});
if (orgs.result && orgs.result.length === 1) {
organization = orgs.result[0].id ?? "";
suffix = orgDomain;
@@ -357,7 +361,7 @@ export async function GET(request: NextRequest) {
idpId = matched?.[1] ?? "";
const identityProviders = await getActiveIdentityProviders({
host,
serviceUrl,
orgId: organization ? organization : undefined,
}).then((resp) => {
return resp.identityProviders;
@@ -382,7 +386,7 @@ export async function GET(request: NextRequest) {
}
return startIdentityProviderFlow({
host,
serviceUrl,
idpId,
urls: {
successUrl:
@@ -482,7 +486,7 @@ export async function GET(request: NextRequest) {
* Instead, the server attempts to silently authenticate the user using an existing session or other authentication mechanisms that do not require user interaction
**/
const selectedSession = await findValidSession(
host,
serviceUrl,
sessions,
authRequest,
);
@@ -511,7 +515,7 @@ export async function GET(request: NextRequest) {
};
const { callbackUrl } = await createCallback({
host,
serviceUrl,
req: create(CreateCallbackRequestSchema, {
authRequestId,
callbackKind: {
@@ -524,7 +528,7 @@ export async function GET(request: NextRequest) {
} else {
// check for loginHint, userId hint and valid sessions
let selectedSession = await findValidSession(
host,
serviceUrl,
sessions,
authRequest,
);
@@ -548,7 +552,7 @@ export async function GET(request: NextRequest) {
try {
const { callbackUrl } = await createCallback({
host,
serviceUrl,
req: create(CreateCallbackRequestSchema, {
authRequestId,
callbackKind: {

View File

@@ -18,6 +18,7 @@ import { Spinner } from "./spinner";
// either loginName or sessionId must be provided
type Props = {
host: string | null;
loginName?: string;
sessionId?: string;
authRequestId?: string;
@@ -25,7 +26,6 @@ type Props = {
method: string;
code?: string;
loginSettings?: LoginSettings;
host: string | null;
};
type Inputs = {
@@ -33,6 +33,7 @@ type Inputs = {
};
export function LoginOTP({
host,
loginName,
sessionId,
authRequestId,
@@ -40,7 +41,6 @@ export function LoginOTP({
method,
code,
loginSettings,
host,
}: Props) {
const t = useTranslations("otp");

View File

@@ -7,14 +7,14 @@ import { getSessionCookieById } from "./cookies";
import { getApiUrlOfHeaders } from "./service";
import { getSession } from "./zitadel";
const transport = async (host: string, token: string) => {
const transport = async (serviceUrl: string, token: string) => {
return createServerTransport(token, {
baseUrl: host,
baseUrl: serviceUrl,
});
};
const myUserService = async (host: string, sessionToken: string) => {
const transportPromise = await transport(host, sessionToken);
const myUserService = async (serviceUrl: string, sessionToken: string) => {
const transportPromise = await transport(serviceUrl, sessionToken);
return createUserServiceClient(transportPromise);
};
@@ -26,16 +26,12 @@ export async function setMyPassword({
password: string;
}) {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
if (!instanceUrl) {
throw new Error("No host found");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
const sessionCookie = await getSessionCookieById({ sessionId });
const { session } = await getSession({
host: instanceUrl,
serviceUrl,
sessionId: sessionCookie.id,
sessionToken: sessionCookie.token,
});
@@ -44,7 +40,7 @@ export async function setMyPassword({
return { error: "Could not load session" };
}
const service = await myUserService(instanceUrl, `${sessionCookie.token}`);
const service = await myUserService(serviceUrl, `${sessionCookie.token}`);
if (!session?.factors?.user?.id) {
return { error: "No user id found in session" };

View File

@@ -35,15 +35,10 @@ export async function createSessionAndUpdateCookie(
lifetime?: Duration,
): Promise<Session> {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host) {
throw new Error("Could not get domain");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
const createdSession = await createSessionFromChecks({
host,
serviceUrl,
checks,
challenges,
lifetime,
@@ -51,7 +46,7 @@ export async function createSessionAndUpdateCookie(
if (createdSession) {
return getSession({
host,
serviceUrl,
sessionId: createdSession.sessionId,
sessionToken: createdSession.sessionToken,
}).then((response) => {
@@ -102,15 +97,10 @@ export async function createSessionForIdpAndUpdateCookie(
lifetime?: Duration,
): Promise<Session> {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host) {
throw new Error("Could not get domain");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
const createdSession = await createSessionForUserIdAndIdpIntent({
host,
serviceUrl,
userId,
idpIntent,
lifetime,
@@ -121,7 +111,7 @@ export async function createSessionForIdpAndUpdateCookie(
}
const { session } = await getSession({
host,
serviceUrl,
sessionId: createdSession.sessionId,
sessionToken: createdSession.sessionToken,
});
@@ -169,15 +159,10 @@ export async function setSessionAndUpdateCookie(
lifetime?: Duration,
) {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host) {
throw new Error("Could not get domain");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
return setSession({
host,
serviceUrl,
sessionId: recentCookie.id,
sessionToken: recentCookie.token,
challenges,
@@ -203,7 +188,7 @@ export async function setSessionAndUpdateCookie(
}
return getSession({
host,
serviceUrl,
sessionId: sessionCookie.id,
sessionToken: sessionCookie.token,
}).then((response) => {

View File

@@ -19,6 +19,7 @@ export type StartIDPFlowCommand = {
export async function startIDPFlow(command: StartIDPFlowCommand) {
const _headers = await headers();
const serviceUrl = getApiUrlOfHeaders(_headers);
const host = _headers.get("host");
if (!host) {
@@ -26,7 +27,7 @@ export async function startIDPFlow(command: StartIDPFlowCommand) {
}
return startIdentityProviderFlow({
host,
serviceUrl,
idpId: command.idpId,
urls: {
successUrl: `${host.includes("localhost") ? "http://" : "https://"}${host}${command.successUrl}`,
@@ -59,8 +60,8 @@ export async function createNewSessionFromIdpIntent(
command: CreateNewSessionCommand,
) {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
const serviceUrl = getApiUrlOfHeaders(_headers);
const host = _headers.get("host");
if (!host) {
return { error: "Could not get domain" };
@@ -70,14 +71,17 @@ export async function createNewSessionFromIdpIntent(
throw new Error("No userId or loginName provided");
}
const userResponse = await getUserByID({ host, userId: command.userId });
const userResponse = await getUserByID({
serviceUrl,
userId: command.userId,
});
if (!userResponse || !userResponse.user) {
return { error: "User not found in the system" };
}
const loginSettings = await getLoginSettings({
host,
serviceUrl,
organization: userResponse.user.details?.resourceOwner,
});

View File

@@ -22,7 +22,7 @@ export type RegisterUserResponse = {
export async function inviteUser(command: InviteUserCommand) {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const serviceUrl = getApiUrlOfHeaders(_headers);
const host = _headers.get("host");
if (!host) {
@@ -30,7 +30,7 @@ export async function inviteUser(command: InviteUserCommand) {
}
const human = await addHumanUser({
host: instanceUrl,
serviceUrl,
email: command.email,
firstName: command.firstName,
lastName: command.lastName,
@@ -42,7 +42,11 @@ export async function inviteUser(command: InviteUserCommand) {
return { error: "Could not create user" };
}
const codeResponse = await createInviteCode({ userId: human.userId, host });
const codeResponse = await createInviteCode({
serviceUrl,
urlTemplate: `${host.includes("localhost") ? "http://" : "https://"}${host}/verify?code={{.Code}}&userId={{.UserID}}&organization={{.OrgID}}&invite=true`,
userId: human.userId,
});
if (!codeResponse || !human) {
return { error: "Could not create invite code" };

View File

@@ -34,15 +34,15 @@ const ORG_SUFFIX_REGEX = /(?<=@)(.+)/;
export async function sendLoginname(command: SendLoginnameCommand) {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
const serviceUrl = getApiUrlOfHeaders(_headers);
const host = _headers.get("host");
if (!host) {
throw new Error("Could not get domain");
}
const loginSettingsByContext = await getLoginSettings({
host,
serviceUrl,
organization: command.organization,
});
@@ -51,7 +51,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
}
let searchUsersRequest: SearchUsersCommand = {
host,
serviceUrl,
searchValue: command.loginName,
organizationId: command.organization,
loginSettings: loginSettingsByContext,
@@ -72,7 +72,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
const redirectUserToSingleIDPIfAvailable = async () => {
const identityProviders = await getActiveIdentityProviders({
host,
serviceUrl,
orgId: command.organization,
}).then((resp) => {
return resp.identityProviders;
@@ -80,8 +80,8 @@ export async function sendLoginname(command: SendLoginnameCommand) {
if (identityProviders.length === 1) {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
const serviceUrl = getApiUrlOfHeaders(_headers);
const host = _headers.get("host");
if (!host) {
return { error: "Could not get host" };
@@ -102,7 +102,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
}
const resp = await startIdentityProviderFlow({
host,
serviceUrl,
idpId: identityProviders[0].id,
urls: {
successUrl:
@@ -121,7 +121,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
};
const redirectUserToIDP = async (userId: string) => {
const identityProviders = await listIDPLinks({ host, userId }).then(
const identityProviders = await listIDPLinks({ serviceUrl, userId }).then(
(resp) => {
return resp.result;
},
@@ -129,8 +129,8 @@ export async function sendLoginname(command: SendLoginnameCommand) {
if (identityProviders.length === 1) {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
const serviceUrl = getApiUrlOfHeaders(_headers);
const host = _headers.get("host");
if (!host) {
return { error: "Could not get host" };
@@ -138,7 +138,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
const identityProviderId = identityProviders[0].idpId;
const idp = await getIDPByID({ host, id: identityProviderId });
const idp = await getIDPByID({ serviceUrl, id: identityProviderId });
const idpType = idp?.type;
@@ -160,7 +160,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
}
const resp = await startIdentityProviderFlow({
host,
serviceUrl,
idpId: idp.id,
urls: {
successUrl:
@@ -185,7 +185,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
const userId = potentialUsers[0].userId;
const userLoginSettings = await getLoginSettings({
host,
serviceUrl,
organization: user.details?.resourceOwner,
});
@@ -243,7 +243,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
}
const methods = await listAuthenticationMethodTypes({
host,
serviceUrl,
userId: session.factors?.user?.id,
});
@@ -400,12 +400,12 @@ export async function sendLoginname(command: SendLoginnameCommand) {
const suffix = matched?.[1] ?? "";
// this just returns orgs where the suffix is set as primary domain
const orgs = await getOrgsByDomain({ host, domain: suffix });
const orgs = await getOrgsByDomain({ serviceUrl, domain: suffix });
const orgToCheckForDiscovery =
orgs.result && orgs.result.length === 1 ? orgs.result[0].id : undefined;
const orgLoginSettings = await getLoginSettings({
host,
serviceUrl,
organization: orgToCheckForDiscovery,
});
if (orgLoginSettings?.allowDomainDiscovery) {

View File

@@ -27,12 +27,7 @@ export type SetOTPCommand = {
export async function setOTP(command: SetOTPCommand) {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host) {
throw new Error("Could not get domain");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
const recentSession = command.sessionId
? await getSessionCookieById({ sessionId: command.sessionId }).catch(
@@ -68,7 +63,7 @@ export async function setOTP(command: SetOTPCommand) {
}
const loginSettings = await getLoginSettings({
host,
serviceUrl,
organization: command.organization,
});

View File

@@ -43,8 +43,8 @@ export async function registerPasskeyLink(
const { sessionId } = command;
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
const serviceUrl = getApiUrlOfHeaders(_headers);
const host = _headers.get("host");
if (!host) {
throw new Error("Could not get domain");
@@ -52,7 +52,7 @@ export async function registerPasskeyLink(
const sessionCookie = await getSessionCookieById({ sessionId });
const session = await getSession({
host,
serviceUrl,
sessionId: sessionCookie.id,
sessionToken: sessionCookie.token,
});
@@ -72,7 +72,7 @@ export async function registerPasskeyLink(
// use session token to add the passkey
const registerLink = await createPasskeyRegistrationLink({
host,
serviceUrl,
userId,
});
@@ -81,7 +81,7 @@ export async function registerPasskeyLink(
}
return registerPasskey({
host,
serviceUrl,
userId,
code: registerLink.code,
domain: hostname,
@@ -90,12 +90,7 @@ export async function registerPasskeyLink(
export async function verifyPasskeyRegistration(command: VerifyPasskeyCommand) {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host) {
throw new Error("Could not get domain");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
// if no name is provided, try to generate one from the user agent
let passkeyName = command.passkeyName;
@@ -113,7 +108,7 @@ export async function verifyPasskeyRegistration(command: VerifyPasskeyCommand) {
sessionId: command.sessionId,
});
const session = await getSession({
host,
serviceUrl,
sessionId: sessionCookie.id,
sessionToken: sessionCookie.token,
});
@@ -124,7 +119,7 @@ export async function verifyPasskeyRegistration(command: VerifyPasskeyCommand) {
}
return zitadelVerifyPasskeyRegistration({
host,
serviceUrl,
request: create(VerifyPasskeyRegistrationRequestSchema, {
passkeyId: command.passkeyId,
publicKeyCredential: command.publicKeyCredential,
@@ -158,14 +153,9 @@ export async function sendPasskey(command: SendPasskeyCommand) {
}
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
const serviceUrl = getApiUrlOfHeaders(_headers);
if (!host) {
return { error: "Could not get host" };
}
const loginSettings = await getLoginSettings({ host, organization });
const loginSettings = await getLoginSettings({ serviceUrl, organization });
const lifetime = checks?.webAuthN
? loginSettings?.multiFactorCheckLifetime // TODO different lifetime for webauthn u2f/passkey
@@ -186,7 +176,7 @@ export async function sendPasskey(command: SendPasskeyCommand) {
}
const userResponse = await getUserByID({
host,
serviceUrl,
userId: session?.factors?.user?.id,
});

View File

@@ -45,15 +45,15 @@ type ResetPasswordCommand = {
export async function resetPassword(command: ResetPasswordCommand) {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
const serviceUrl = getApiUrlOfHeaders(_headers);
const host = _headers.get("host");
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const users = await listUsers({
serviceUrl: instanceUrl,
serviceUrl,
loginName: command.loginName,
organizationId: command.organization,
});
@@ -68,7 +68,7 @@ export async function resetPassword(command: ResetPasswordCommand) {
const userId = users.result[0].userId;
return passwordReset({
serviceUrl: instanceUrl,
serviceUrl,
userId,
urlTemplate:
`${host.includes("localhost") ? "http://" : "https://"}${host}/password/set?code={{.Code}}&userId={{.UserID}}&organization={{.OrgID}}` +
@@ -85,12 +85,7 @@ export type UpdateSessionCommand = {
export async function sendPassword(command: UpdateSessionCommand) {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
let sessionCookie = await getSessionCookieByLoginName({
loginName: command.loginName,
@@ -105,7 +100,7 @@ export async function sendPassword(command: UpdateSessionCommand) {
if (!sessionCookie) {
const users = await listUsers({
host,
serviceUrl,
loginName: command.loginName,
organizationId: command.organization,
});
@@ -119,7 +114,7 @@ export async function sendPassword(command: UpdateSessionCommand) {
});
loginSettings = await getLoginSettings({
host,
serviceUrl,
organization: command.organization,
});
@@ -147,7 +142,7 @@ export async function sendPassword(command: UpdateSessionCommand) {
}
const userResponse = await getUserByID({
host,
serviceUrl,
userId: session?.factors?.user?.id,
});
@@ -160,7 +155,7 @@ export async function sendPassword(command: UpdateSessionCommand) {
if (!loginSettings) {
loginSettings = await getLoginSettings({
host,
serviceUrl,
organization:
command.organization ?? session.factors?.user?.organizationId,
});
@@ -205,7 +200,7 @@ export async function sendPassword(command: UpdateSessionCommand) {
let authMethods;
if (command.checks && command.checks.password && session.factors?.user?.id) {
const response = await listAuthenticationMethodTypes({
host,
serviceUrl,
userId: session.factors.user.id,
});
if (response.authMethodTypes && response.authMethodTypes.length) {
@@ -260,15 +255,10 @@ export async function changePassword(command: {
password: string;
}) {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
// check for init state
const { user } = await getUserByID({ host, userId: command.userId });
const { user } = await getUserByID({ serviceUrl, userId: command.userId });
if (!user || user.userId !== command.userId) {
return { error: "Could not send Password Reset Link" };
@@ -276,7 +266,7 @@ export async function changePassword(command: {
const userId = user.userId;
return setUserPassword({
host,
serviceUrl,
userId,
password: command.password,
user,
@@ -294,17 +284,12 @@ export async function checkSessionAndSetPassword({
password,
}: CheckSessionAndSetPasswordCommand) {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
if (!instanceUrl) {
throw new Error("No host found");
}
const host = instanceUrl;
const serviceUrl = getApiUrlOfHeaders(_headers);
const sessionCookie = await getSessionCookieById({ sessionId });
const { session } = await getSession({
host: instanceUrl,
serviceUrl,
sessionId: sessionCookie.id,
sessionToken: sessionCookie.token,
});
@@ -322,7 +307,7 @@ export async function checkSessionAndSetPassword({
// check if the user has no password set in order to set a password
const authmethods = await listAuthenticationMethodTypes({
host,
serviceUrl,
userId: session.factors.user.id,
});
@@ -342,7 +327,7 @@ export async function checkSessionAndSetPassword({
);
const loginSettings = await getLoginSettings({
host: instanceUrl,
serviceUrl,
organization: session.factors.user.organizationId,
});
@@ -352,7 +337,7 @@ export async function checkSessionAndSetPassword({
// if the user has no MFA but MFA is enforced, we can set a password otherwise we use the token of the user
if (forceMfa && hasNoMFAMethods) {
return setPassword({ host, payload }).catch((error) => {
return setPassword({ serviceUrl, payload }).catch((error) => {
// throw error if failed precondition (ex. User is not yet initialized)
if (error.code === 9 && error.message) {
return { error: "Failed precondition" };
@@ -363,17 +348,17 @@ export async function checkSessionAndSetPassword({
} else {
const transport = async (host: string, token: string) => {
return createServerTransport(token, {
baseUrl: host,
baseUrl: serviceUrl,
});
};
const myUserService = async (host: string, sessionToken: string) => {
const transportPromise = await transport(host, sessionToken);
const transportPromise = await transport(serviceUrl, sessionToken);
return createUserServiceClient(transportPromise);
};
const selfService = await myUserService(
instanceUrl,
serviceUrl,
`${sessionCookie.token}`,
);

View File

@@ -29,15 +29,15 @@ export type RegisterUserResponse = {
};
export async function registerUser(command: RegisterUserCommand) {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
const serviceUrl = getApiUrlOfHeaders(_headers);
const host = _headers.get("host");
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const addResponse = await addHumanUser({
host,
serviceUrl,
email: command.email,
firstName: command.firstName,
lastName: command.lastName,
@@ -50,7 +50,7 @@ export async function registerUser(command: RegisterUserCommand) {
}
const loginSettings = await getLoginSettings({
host,
serviceUrl,
organization: command.organization,
});
@@ -91,7 +91,7 @@ export async function registerUser(command: RegisterUserCommand) {
return { redirect: "/passkey/set?" + params };
} else {
const userResponse = await getUserByID({
host,
serviceUrl,
userId: session?.factors?.user?.id,
});

View File

@@ -25,15 +25,10 @@ export async function continueWithSession({
...session
}: Session & { authRequestId?: string }) {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
const loginSettings = await getLoginSettings({
host,
serviceUrl,
organization: session.factors?.user?.organizationId,
});
@@ -93,8 +88,8 @@ export async function updateSession(options: UpdateSessionCommand) {
}
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
const serviceUrl = getApiUrlOfHeaders(_headers);
const host = _headers.get("host");
if (!host) {
return { error: "Could not get host" };
@@ -111,7 +106,7 @@ export async function updateSession(options: UpdateSessionCommand) {
challenges.webAuthN.domain = hostname;
}
const loginSettings = await getLoginSettings({ host, organization });
const loginSettings = await getLoginSettings({ serviceUrl, organization });
const lifetime = checks?.webAuthN
? loginSettings?.multiFactorCheckLifetime // TODO different lifetime for webauthn u2f/passkey
@@ -135,7 +130,7 @@ export async function updateSession(options: UpdateSessionCommand) {
let authMethods;
if (checks && checks.password && session.factors?.user?.id) {
const response = await listAuthenticationMethodTypes({
host,
serviceUrl,
userId: session.factors.user.id,
});
if (response.authMethodTypes && response.authMethodTypes.length) {
@@ -157,19 +152,14 @@ type ClearSessionOptions = {
export async function clearSession(options: ClearSessionOptions) {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
const { sessionId } = options;
const session = await getSessionCookieById({ sessionId });
const deletedSession = await deleteSession({
host,
serviceUrl,
sessionId: session.id,
sessionToken: session.token,
});
@@ -185,17 +175,12 @@ type CleanupSessionCommand = {
export async function cleanupSession({ sessionId }: CleanupSessionCommand) {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
const sessionCookie = await getSessionCookieById({ sessionId });
const deleteResponse = await deleteSession({
host,
serviceUrl,
sessionId: sessionCookie.id,
sessionToken: sessionCookie.token,
});

View File

@@ -21,8 +21,8 @@ type VerifyU2FCommand = {
export async function addU2F(command: RegisterU2FCommand) {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
const serviceUrl = getApiUrlOfHeaders(_headers);
const host = _headers.get("host");
if (!host || typeof host !== "string") {
throw new Error("No host found");
@@ -37,7 +37,7 @@ export async function addU2F(command: RegisterU2FCommand) {
}
const session = await getSession({
host,
serviceUrl,
sessionId: sessionCookie.id,
sessionToken: sessionCookie.token,
});
@@ -54,13 +54,13 @@ export async function addU2F(command: RegisterU2FCommand) {
return { error: "Could not get session" };
}
return registerU2F({ host, userId, domain: hostname });
return registerU2F({ serviceUrl, userId, domain: hostname });
}
export async function verifyU2F(command: VerifyU2FCommand) {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
const serviceUrl = getApiUrlOfHeaders(_headers);
const host = _headers.get("host");
if (!host || typeof host !== "string") {
throw new Error("No host found");
@@ -81,7 +81,7 @@ export async function verifyU2F(command: VerifyU2FCommand) {
});
const session = await getSession({
host,
serviceUrl,
sessionId: sessionCookie.id,
sessionToken: sessionCookie.token,
});
@@ -99,5 +99,5 @@ export async function verifyU2F(command: VerifyU2FCommand) {
userId,
});
return verifyU2FRegistration({ host, request });
return verifyU2FRegistration({ serviceUrl, request });
}

View File

@@ -30,15 +30,10 @@ export async function verifyTOTP(
organization?: string,
) {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
return loadMostRecentSession({
host,
serviceUrl,
sessionParams: {
loginName,
organization,
@@ -46,7 +41,7 @@ export async function verifyTOTP(
}).then((session) => {
if (session?.factors?.user?.id) {
return verifyTOTPRegistration({
host,
serviceUrl,
code,
userId: session.factors.user.id,
});
@@ -67,23 +62,18 @@ type VerifyUserByEmailCommand = {
export async function sendVerification(command: VerifyUserByEmailCommand) {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
const verifyResponse = command.isInvite
? await verifyInviteCode({
host,
serviceUrl,
userId: command.userId,
verificationCode: command.code,
}).catch(() => {
return { error: "Could not verify invite" };
})
: await verifyEmail({
host,
serviceUrl,
userId: command.userId,
verificationCode: command.code,
}).catch(() => {
@@ -114,7 +104,7 @@ export async function sendVerification(command: VerifyUserByEmailCommand) {
}
session = await getSession({
host,
serviceUrl,
sessionId: sessionCookie.id,
sessionToken: sessionCookie.token,
}).then((response) => {
@@ -128,7 +118,7 @@ export async function sendVerification(command: VerifyUserByEmailCommand) {
}
const userResponse = await getUserByID({
host,
serviceUrl,
userId: session?.factors?.user?.id,
});
@@ -138,7 +128,10 @@ export async function sendVerification(command: VerifyUserByEmailCommand) {
user = userResponse.user;
} else {
const userResponse = await getUserByID({ host, userId: command.userId });
const userResponse = await getUserByID({
serviceUrl,
userId: command.userId,
});
if (!userResponse || !userResponse.user) {
return { error: "Could not load user" };
@@ -175,12 +168,12 @@ export async function sendVerification(command: VerifyUserByEmailCommand) {
}
const loginSettings = await getLoginSettings({
host,
serviceUrl,
organization: user.details?.resourceOwner,
});
const authMethodResponse = await listAuthenticationMethodTypes({
host,
serviceUrl,
userId: user.userId,
});
@@ -252,41 +245,36 @@ type resendVerifyEmailCommand = {
export async function resendVerification(command: resendVerifyEmailCommand) {
const _headers = await headers();
const serviceUrl = getApiUrlOfHeaders(_headers);
const host = _headers.get("host");
if (!serviceUrl) {
return { error: "No host found" };
}
if (!host) {
return { error: "No host found" };
}
return command.isInvite
? resendInviteCode({ serviceUrl, host, userId: command.userId })
? resendInviteCode({ serviceUrl, userId: command.userId })
: resendEmailCode({
userId: command.userId,
serviceUrl,
host,
authRequestId: command.authRequestId,
urlTemplate:
`${host.includes("localhost") ? "http://" : "https://"}${host}/password/set?code={{.Code}}&userId={{.UserID}}&organization={{.OrgID}}` +
(command.authRequestId
? `&authRequestId=${command.authRequestId}`
: ""),
});
}
type sendEmailCommand = {
serviceUrl: string;
userId: string;
authRequestId?: string;
urlTemplate: string;
};
export async function sendEmailCode(command: sendEmailCommand) {
return zitadelSendEmailCode({
userId: command.userId,
serviceUrl: command.serviceUrl,
authRequestId: command.authRequestId,
urlTemplate:
`${host.includes("localhost") ? "http://" : "https://"}${host}/verify?code={{.Code}}&userId={{.UserID}}&organization={{.OrgID}}&invite=true` +
(authRequestId ? `&authRequestId=${authRequestId}` : ""),
urlTemplate: command.urlTemplate,
});
}
@@ -302,12 +290,7 @@ export async function sendVerificationRedirectWithoutCheck(
command: SendVerificationRedirectWithoutCheckCommand,
) {
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const host = instanceUrl;
if (!host || typeof host !== "string") {
throw new Error("No host found");
}
const serviceUrl = getApiUrlOfHeaders(_headers);
if (!("loginName" in command || "userId" in command)) {
return { error: "No userId, nor loginname provided" };
@@ -329,7 +312,7 @@ export async function sendVerificationRedirectWithoutCheck(
}
session = await getSession({
host,
serviceUrl,
sessionId: sessionCookie.id,
sessionToken: sessionCookie.token,
}).then((response) => {
@@ -343,7 +326,7 @@ export async function sendVerificationRedirectWithoutCheck(
}
const userResponse = await getUserByID({
host,
serviceUrl,
userId: session?.factors?.user?.id,
});
@@ -353,7 +336,10 @@ export async function sendVerificationRedirectWithoutCheck(
user = userResponse.user;
} else if ("userId" in command) {
const userResponse = await getUserByID({ host, userId: command.userId });
const userResponse = await getUserByID({
serviceUrl,
userId: command.userId,
});
if (!userResponse?.user) {
return { error: "Could not load user" };
@@ -390,7 +376,7 @@ export async function sendVerificationRedirectWithoutCheck(
}
const authMethodResponse = await listAuthenticationMethodTypes({
host,
serviceUrl,
userId: user.userId,
});
@@ -415,7 +401,7 @@ export async function sendVerificationRedirectWithoutCheck(
}
const loginSettings = await getLoginSettings({
host,
serviceUrl,
organization: user.details?.resourceOwner,
});

View File

@@ -19,16 +19,16 @@ type ServiceClass =
export async function createServiceForHost<T extends ServiceClass>(
service: T,
host: string,
serviceUrl: string,
) {
const token = await systemAPIToken();
if (!host || !token) {
if (!serviceUrl || !token) {
throw new Error("No instance url or token found");
}
const transport = createServerTransport(token, {
baseUrl: host,
baseUrl: serviceUrl,
});
return createClientFor<T>(service)(transport);

View File

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

View File

@@ -1,6 +1,4 @@
import { Client, create, Duration } from "@zitadel/client";
import { createServerTransport } from "@zitadel/client/node";
import { createSystemServiceClient } from "@zitadel/client/v1";
import { makeReqCtx } from "@zitadel/client/v2";
import { IdentityProviderService } from "@zitadel/proto/zitadel/idp/v2/idp_service_pb";
import { TextQueryMethod } from "@zitadel/proto/zitadel/object/v2/object_pb";
@@ -44,7 +42,6 @@ import {
VerifyU2FRegistrationRequest,
} from "@zitadel/proto/zitadel/user/v2/user_service_pb";
import { unstable_cacheLife as cacheLife } from "next/cache";
import { systemAPIToken } from "./api";
import { createServiceForHost } from "./service";
const useCache = process.env.DEBUG !== "true";
@@ -56,16 +53,6 @@ async function cacheWrapper<T>(callback: Promise<T>) {
return callback;
}
const systemService = async () => {
const systemToken = await systemAPIToken();
const transport = createServerTransport(systemToken, {
baseUrl: process.env.AUDIENCE,
});
return createSystemServiceClient(transport);
};
export async function getBrandingSettings({
serviceUrl,
organization,
@@ -87,11 +74,11 @@ export async function getLoginSettings({
serviceUrl,
organization,
}: {
serviceurl: string;
serviceUrl: string;
organization?: string;
}) {
const settingsService: Client<typeof SettingsService> =
await createServiceForHost(SettingsService, host);
await createServiceForHost(SettingsService, serviceUrl);
const callback = settingsService
.getLoginSettings({ ctx: makeReqCtx(organization) }, {})
@@ -104,7 +91,7 @@ export async function listIDPLinks({
serviceUrl,
userId,
}: {
serviceurl: string;
serviceUrl: string;
userId: string;
}) {
const userService: Client<typeof UserService> = await createServiceForHost(
@@ -119,7 +106,7 @@ export async function addOTPEmail({
serviceUrl,
userId,
}: {
serviceurl: string;
serviceUrl: string;
userId: string;
}) {
const userService: Client<typeof UserService> = await createServiceForHost(
@@ -134,7 +121,7 @@ export async function addOTPSMS({
serviceUrl,
userId,
}: {
serviceurl: string;
serviceUrl: string;
userId: string;
}) {
const userService: Client<typeof UserService> = await createServiceForHost(
@@ -149,7 +136,7 @@ export async function registerTOTP({
serviceUrl,
userId,
}: {
serviceurl: string;
serviceUrl: string;
userId: string;
}) {
const userService: Client<typeof UserService> = await createServiceForHost(
@@ -160,9 +147,13 @@ export async function registerTOTP({
return userService.registerTOTP({ userId }, {});
}
export async function getGeneralSettings({ host }: { serviceurl: string }) {
export async function getGeneralSettings({
serviceUrl,
}: {
serviceUrl: string;
}) {
const settingsService: Client<typeof SettingsService> =
await createServiceForHost(SettingsService, host);
await createServiceForHost(SettingsService, serviceUrl);
const callback = settingsService
.getGeneralSettings({}, {})
@@ -175,11 +166,11 @@ export async function getLegalAndSupportSettings({
serviceUrl,
organization,
}: {
serviceurl: string;
serviceUrl: string;
organization?: string;
}) {
const settingsService: Client<typeof SettingsService> =
await createServiceForHost(SettingsService, host);
await createServiceForHost(SettingsService, serviceUrl);
const callback = settingsService
.getLegalAndSupportSettings({ ctx: makeReqCtx(organization) }, {})
@@ -192,11 +183,11 @@ export async function getPasswordComplexitySettings({
serviceUrl,
organization,
}: {
serviceurl: string;
serviceUrl: string;
organization?: string;
}) {
const settingsService: Client<typeof SettingsService> =
await createServiceForHost(SettingsService, host);
await createServiceForHost(SettingsService, serviceUrl);
const callback = settingsService
.getPasswordComplexitySettings({ ctx: makeReqCtx(organization) })
@@ -211,13 +202,13 @@ export async function createSessionFromChecks({
challenges,
lifetime,
}: {
serviceurl: string;
serviceUrl: string;
checks: Checks;
challenges: RequestChallenges | undefined;
lifetime?: Duration;
}) {
const sessionService: Client<typeof SessionService> =
await createServiceForHost(SessionService, host);
await createServiceForHost(SessionService, serviceUrl);
return sessionService.createSession({ checks, challenges, lifetime }, {});
}
@@ -228,7 +219,7 @@ export async function createSessionForUserIdAndIdpIntent({
idpIntent,
lifetime,
}: {
serviceurl: string;
serviceUrl: string;
userId: string;
idpIntent: {
idpIntentId?: string | undefined;
@@ -237,7 +228,7 @@ export async function createSessionForUserIdAndIdpIntent({
lifetime?: Duration;
}) {
const sessionService: Client<typeof SessionService> =
await createServiceForHost(SessionService, host);
await createServiceForHost(SessionService, serviceUrl);
return sessionService.createSession({
checks: {
@@ -261,7 +252,7 @@ export async function setSession({
checks,
lifetime,
}: {
serviceurl: string;
serviceUrl: string;
sessionId: string;
sessionToken: string;
challenges: RequestChallenges | undefined;
@@ -269,7 +260,7 @@ export async function setSession({
lifetime?: Duration;
}) {
const sessionService: Client<typeof SessionService> =
await createServiceForHost(SessionService, host);
await createServiceForHost(SessionService, serviceUrl);
return sessionService.setSession(
{
@@ -289,12 +280,12 @@ export async function getSession({
sessionId,
sessionToken,
}: {
serviceurl: string;
serviceUrl: string;
sessionId: string;
sessionToken: string;
}) {
const sessionService: Client<typeof SessionService> =
await createServiceForHost(SessionService, host);
await createServiceForHost(SessionService, serviceUrl);
return sessionService.getSession({ sessionId, sessionToken }, {});
}
@@ -304,12 +295,12 @@ export async function deleteSession({
sessionId,
sessionToken,
}: {
serviceurl: string;
serviceUrl: string;
sessionId: string;
sessionToken: string;
}) {
const sessionService: Client<typeof SessionService> =
await createServiceForHost(SessionService, host);
await createServiceForHost(SessionService, serviceUrl);
return sessionService.deleteSession({ sessionId, sessionToken }, {});
}
@@ -321,7 +312,7 @@ type ListSessionsCommand = {
export async function listSessions({ serviceUrl, ids }: ListSessionsCommand) {
const sessionService: Client<typeof SessionService> =
await createServiceForHost(SessionService, host);
await createServiceForHost(SessionService, serviceUrl);
return sessionService.listSessions(
{
@@ -460,27 +451,24 @@ export async function resendInviteCode({
export async function sendEmailCode({
serviceUrl,
urlTemplate
userId,
authRequestId,
urlTemplate,
}: {
serviceUrl: string;
userId: string;
authRequestId?: string;
urlTemplate: string;
}) {
let medium = create(SendEmailCodeRequestSchema, { userId });
if (host) {
medium = create(SendEmailCodeRequestSchema, {
...medium,
verification: {
case: "sendCode",
value: create(SendEmailVerificationCodeSchema, {
urlTemplate,
}),
},
});
}
medium = create(SendEmailCodeRequestSchema, {
...medium,
verification: {
case: "sendCode",
value: create(SendEmailVerificationCodeSchema, {
urlTemplate,
}),
},
});
const userService: Client<typeof UserService> = await createServiceForHost(
UserService,
@@ -492,21 +480,21 @@ export async function sendEmailCode({
export async function createInviteCode({
serviceUrl,
urlTemplate,
userId,
}: {
serviceUrl: string;
urlTemplate: string;
userId: string;
}) {
let medium = create(SendInviteCodeSchema, {
applicationName: "Typescript Login",
});
if (host) {
medium = {
...medium,
urlTemplate: `${host.includes("localhost") ? "http://" : "https://"}${host}/verify?code={{.Code}}&userId={{.UserID}}&organization={{.OrgID}}&invite=true`,
};
}
medium = {
...medium,
urlTemplate,
};
const userService: Client<typeof UserService> = await createServiceForHost(
UserService,
@@ -802,7 +790,7 @@ export async function getDefaultOrg({
serviceUrl: string;
}): Promise<Organization | null> {
const orgService: Client<typeof OrganizationService> =
await createServiceForHost(OrganizationService, host);
await createServiceForHost(OrganizationService, serviceUrl);
return orgService
.listOrganizations(
@@ -829,7 +817,7 @@ export async function getOrgsByDomain({
domain: string;
}) {
const orgService: Client<typeof OrganizationService> =
await createServiceForHost(OrganizationService, host);
await createServiceForHost(OrganizationService, serviceUrl);
return orgService.listOrganizations(
{
@@ -896,7 +884,7 @@ export async function getAuthRequest({
serviceUrl: string;
authRequestId: string;
}) {
const oidcService = await createServiceForHost(OIDCService, host);
const oidcService = await createServiceForHost(OIDCService, serviceUrl);
return oidcService.getAuthRequest({
authRequestId,
@@ -910,7 +898,7 @@ export async function createCallback({
serviceUrl: string;
req: CreateCallbackRequest;
}) {
const oidcService = await createServiceForHost(OIDCService, host);
const oidcService = await createServiceForHost(OIDCService, serviceUrl);
return oidcService.createCallback(req);
}
@@ -940,28 +928,22 @@ export async function verifyEmail({
export async function resendEmailCode({
serviceUrl,
host,
userId,
authRequestId,
urlTemplate,
}: {
serviceUrl: string;
host: string;
userId: string;
authRequestId?: string;
urlTemplate: string;
}) {
let request: ResendEmailCodeRequest = create(ResendEmailCodeRequestSchema, {
userId,
});
if (host) {
const medium = create(SendEmailVerificationCodeSchema, {
urlTemplate:
`${host.includes("localhost") ? "http://" : "https://"}${host}/password/set?code={{.Code}}&userId={{.UserID}}&organization={{.OrgID}}` +
(authRequestId ? `&authRequestId=${authRequestId}` : ""),
});
const medium = create(SendEmailVerificationCodeSchema, {
urlTemplate,
});
request = { ...request, verification: { case: "sendCode", value: medium } };
}
request = { ...request, verification: { case: "sendCode", value: medium } };
const userService: Client<typeof UserService> = await createServiceForHost(
UserService,
@@ -999,7 +981,7 @@ export async function getIDPByID({
id: string;
}) {
const idpService: Client<typeof IdentityProviderService> =
await createServiceForHost(IdentityProviderService, host);
await createServiceForHost(IdentityProviderService, serviceUrl);
return idpService.getIDPByID({ id }, {}).then((resp) => resp.idp);
}
@@ -1033,21 +1015,21 @@ export async function addIDPLink({
export async function passwordReset({
serviceUrl,
urlTemplate,
userId,
urlTemplate,
}: {
serviceUrl: string;
urlTemplate: string;
userId: string;
urlTemplate?: string;
}) {
let medium = create(SendPasswordResetLinkSchema, {
notificationType: NotificationType.Email,
});
medium = {
...medium,
urlTemplate,
};
medium = {
...medium,
urlTemplate,
};
const userService: Client<typeof UserService> = await createServiceForHost(
UserService,
@@ -1238,7 +1220,7 @@ export async function getActiveIdentityProviders({
props.linkingAllowed = linking_allowed;
}
const settingsService: Client<typeof SettingsService> =
await createServiceForHost(SettingsService, host);
await createServiceForHost(SettingsService, serviceUrl);
return settingsService.getActiveIdentityProviders(props, {});
}

View File

@@ -22,9 +22,9 @@ export async function middleware(request: NextRequest) {
// }
const _headers = await headers();
const instanceUrl = getApiUrlOfHeaders(_headers);
const serviceUrl = getApiUrlOfHeaders(_headers);
const instanceHost = `${instanceUrl}`.replace("https://", "");
const instanceHost = `${serviceUrl}`.replace("https://", "");
const requestHeaders = new Headers(request.headers);
requestHeaders.set(
@@ -43,7 +43,7 @@ export async function middleware(request: NextRequest) {
responseHeaders.set("Access-Control-Allow-Origin", "*");
responseHeaders.set("Access-Control-Allow-Headers", "*");
request.nextUrl.href = `${instanceUrl}${request.nextUrl.pathname}${request.nextUrl.search}`;
request.nextUrl.href = `${serviceUrl}${request.nextUrl.pathname}${request.nextUrl.search}`;
return NextResponse.rewrite(request.nextUrl, {
request: {
headers: requestHeaders,

View File

@@ -11,7 +11,8 @@
"SYSTEM_USER_PRIVATE_KEY",
"ZITADEL_API_URL",
"ZITADEL_SERVICE_USER_ID",
"ZITADEL_SERVICE_USER_TOKEN"
"ZITADEL_SERVICE_USER_TOKEN",
"NEXT_PUBLIC_BASE_PATH"
],
"tasks": {
"generate": {