Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multitenancy #211

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
33 changes: 33 additions & 0 deletions apps/login/next-env-vars.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
declare namespace NodeJS {
interface ProcessEnv {
/**
* The system api url
*/
AUDIENCE: string;

/**
* The system api service user ID
*/
SYSTEM_USER_ID: string;

/**
* The service user key
*/
SYSTEM_USER_PRIVATE_KEY: string;

/**
* The instance url
*/
ZITADEL_API_URL: string;

/**
* The service user id for the instance
*/
ZITADEL_USER_ID: string;

/**
* The service user token for the instance
*/
ZITADEL_USER_TOKEN: string;
}
}
1 change: 1 addition & 0 deletions apps/login/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"@zitadel/proto": "workspace:*",
"clsx": "1.2.1",
"copy-to-clipboard": "^3.3.3",
"jose": "^5.3.0",
"deepmerge": "^4.3.1",
"moment": "^2.29.4",
"next": "14.2.14",
Expand Down
2 changes: 1 addition & 1 deletion apps/login/src/app/(login)/idp/[provider]/success/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ export default async function Page({
userName: idpInformation.userName,
},
foundUser.userId,
).catch((error) => {
).catch(() => {
return (
<DynamicTheme branding={branding}>
<div className="flex flex-col items-center space-y-4">
Expand Down
13 changes: 2 additions & 11 deletions apps/login/src/app/(login)/idp/page.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
import { DynamicTheme } from "@/components/dynamic-theme";
import { SignInWithIdp } from "@/components/sign-in-with-idp";
import { getBrandingSettings, settingsService } from "@/lib/zitadel";
import { makeReqCtx } from "@zitadel/client/v2";
import { getActiveIdentityProviders, getBrandingSettings } from "@/lib/zitadel";
import { getLocale, getTranslations } from "next-intl/server";

function getIdentityProviders(orgId?: string) {
return settingsService
.getActiveIdentityProviders({ ctx: makeReqCtx(orgId) }, {})
.then((resp) => {
return resp.identityProviders;
});
}

export default async function Page({
searchParams,
}: {
Expand All @@ -23,7 +14,7 @@ export default async function Page({
const authRequestId = searchParams?.authRequestId;
const organization = searchParams?.organization;

const identityProviders = await getIdentityProviders(organization);
const identityProviders = await getActiveIdentityProviders(organization);

const host = process.env.VERCEL_URL
? `https://${process.env.VERCEL_URL}`
Expand Down
15 changes: 3 additions & 12 deletions apps/login/src/app/(login)/loginname/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,13 @@ import { DynamicTheme } from "@/components/dynamic-theme";
import { SignInWithIdp } from "@/components/sign-in-with-idp";
import { UsernameForm } from "@/components/username-form";
import {
getActiveIdentityProviders,
getBrandingSettings,
getLegalAndSupportSettings,
getLoginSettings,
settingsService,
} from "@/lib/zitadel";
import { makeReqCtx } from "@zitadel/client/v2";
import { getLocale, getTranslations } from "next-intl/server";

function getIdentityProviders(orgId?: string) {
return settingsService
.getActiveIdentityProviders({ ctx: makeReqCtx(orgId) }, {})
.then((resp) => {
return resp.identityProviders;
});
}

export default async function Page({
searchParams,
}: {
Expand All @@ -34,7 +25,7 @@ export default async function Page({
const loginSettings = await getLoginSettings(organization);
const legal = await getLegalAndSupportSettings();

const identityProviders = await getIdentityProviders(organization);
const identityProviders = await getActiveIdentityProviders(organization);

const host = process.env.VERCEL_URL
? `https://${process.env.VERCEL_URL}`
Expand All @@ -55,7 +46,7 @@ export default async function Page({
submit={submit}
allowRegister={!!loginSettings?.allowRegister}
>
{legal && identityProviders && process.env.ZITADEL_API_URL && (
{legal && identityProviders && (
<SignInWithIdp
host={host}
identityProviders={identityProviders}
Expand Down
10 changes: 8 additions & 2 deletions apps/login/src/app/(login)/register/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { RegisterFormWithoutPassword } from "@/components/register-form-without-
import { SetPasswordForm } from "@/components/set-password-form";
import {
getBrandingSettings,
getDefaultOrg,
getLegalAndSupportSettings,
getPasswordComplexitySettings,
} from "@/lib/zitadel";
Expand All @@ -16,11 +17,16 @@ export default async function Page({
const locale = getLocale();
const t = await getTranslations({ locale, namespace: "register" });

const { firstname, lastname, email, organization, authRequestId } =
let { firstname, lastname, email, organization, authRequestId } =
searchParams;

if (!organization) {
// TODO: get default organization
const org = await getDefaultOrg();
if (!org) {
throw new Error("No default organization found");
}

organization = org.id;
}

const setPassword = !!(firstname && lastname && email);
Expand Down
4 changes: 1 addition & 3 deletions apps/login/src/app/login/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,7 @@ export async function GET(request: NextRequest) {

const identityProviders = await getActiveIdentityProviders(
organization ? organization : undefined,
).then((resp) => {
return resp.identityProviders;
});
);

const idp = identityProviders.find((idp) => idp.id === idpId);

Expand Down
36 changes: 36 additions & 0 deletions apps/login/src/lib/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { importPKCS8, SignJWT } from "jose";
import { getInstanceByHost } from "./zitadel";

export async function getInstanceUrl(host: string): Promise<string> {
const instance = await getInstanceByHost(host);
const generatedDomain = instance.domains.find(
(domain) => domain.generated === true,
);

if (!generatedDomain?.domain) {
throw new Error("No generated domain found");
}

console.log(`host: ${host}, api: ${generatedDomain?.domain}`);

return generatedDomain?.domain;
}

export async function systemAPIToken() {
const audience = process.env.AUDIENCE;
const userID = process.env.SYSTEM_USER_ID;
const key = process.env.SYSTEM_USER_PRIVATE_KEY;

const decodedToken = Buffer.from(key, "base64").toString("utf-8");

const token = new SignJWT({})
.setProtectedHeader({ alg: "RS256" })
.setIssuedAt()
.setExpirationTime("1h")
.setIssuer(userID)
.setSubject(userID)
.setAudience(audience)
.sign(await importPKCS8(decodedToken, "RS256"));

return token;
}
20 changes: 7 additions & 13 deletions apps/login/src/lib/self.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,21 @@
"use server";

import {
createSessionServiceClient,
createUserServiceClient,
} from "@zitadel/client/v2";
import { createUserServiceClient } from "@zitadel/client/v2";
import { createServerTransport } from "@zitadel/node";
import { getSessionCookieById } from "./cookies";

const transport = (token: string) =>
const transport = (url: string, token: string) =>
createServerTransport(token, {
baseUrl: process.env.ZITADEL_API_URL!,
baseUrl: url,
httpVersion: "2",
});

const sessionService = (sessionId: string) => {
return getSessionCookieById({ sessionId }).then((session) => {
return createSessionServiceClient(transport(session.token));
});
};

const userService = (sessionId: string) => {
return getSessionCookieById({ sessionId }).then((session) => {
return createUserServiceClient(transport(session.token));
return createUserServiceClient(
// TODO: get baseurl dynamically
transport(process.env.ZITADEL_API_URL, session.token),
);
});
};

Expand Down
4 changes: 1 addition & 3 deletions apps/login/src/lib/server/loginname.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,7 @@ export async function sendLoginname(command: SendLoginnameCommand) {
const redirectUserToSingleIDPIfAvailable = async () => {
const identityProviders = await getActiveIdentityProviders(
command.organization,
).then((resp) => {
return resp.identityProviders;
});
);

if (identityProviders.length === 1) {
const host = headers().get("host");
Expand Down
Loading
Loading