From c86e959a6c3543a4264be71a6811543f147758bb Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Thu, 6 Apr 2023 18:57:58 +0200 Subject: [PATCH] client setup --- packages/zitadel-core/package.json | 4 +++ packages/zitadel-core/src/admin.ts | 31 ++++++++++++++++++++++ packages/zitadel-core/src/auth.ts | 22 ++++++++++++++++ packages/zitadel-core/src/core.ts | 4 ++- packages/zitadel-core/src/management.ts | 32 ++++++++++++++++++++++ packages/zitadel-core/src/middleware.ts | 14 ++++++++++ packages/zitadel-core/src/system.ts | 35 +++++++++++++++++++++++++ pnpm-lock.yaml | 21 ++++++++------- 8 files changed, 153 insertions(+), 10 deletions(-) create mode 100644 packages/zitadel-core/src/admin.ts create mode 100644 packages/zitadel-core/src/auth.ts create mode 100644 packages/zitadel-core/src/management.ts create mode 100644 packages/zitadel-core/src/middleware.ts create mode 100644 packages/zitadel-core/src/system.ts diff --git a/packages/zitadel-core/package.json b/packages/zitadel-core/package.json index 7d11c10192a..5f896ca8238 100644 --- a/packages/zitadel-core/package.json +++ b/packages/zitadel-core/package.json @@ -26,5 +26,9 @@ }, "publishConfig": { "access": "public" + }, + "dependencies": { + "nice-grpc": "2.0.1", + "jose": "^4.13.1" } } diff --git a/packages/zitadel-core/src/admin.ts b/packages/zitadel-core/src/admin.ts new file mode 100644 index 00000000000..52b5640494d --- /dev/null +++ b/packages/zitadel-core/src/admin.ts @@ -0,0 +1,31 @@ +import { CompatServiceDefinition } from "nice-grpc/lib/service-definitions"; + +import { createChannel, createClientFactory } from "nice-grpc"; +import { + AuthServiceClient, + AuthServiceDefinition, +} from "./proto/server/zitadel/auth"; +import { + AdminServiceClient, + AdminServiceDefinition, +} from "./proto/server/zitadel/admin"; +import { authMiddleware } from "./middleware"; + +const createClient = ( + definition: CompatServiceDefinition, + accessToken: string +) => { + const channel = createChannel(process.env.ZITADEL_API_URL); + return createClientFactory() + .use(authMiddleware(accessToken)) + .create(definition, channel) as Client; +}; + +export const getAuth = async () => + createClient(AuthServiceDefinition, ""); + +export const getAdmin = () => + createClient( + AdminServiceDefinition, + process.env.ZITADEL_ADMIN_TOKEN ?? "" + ); diff --git a/packages/zitadel-core/src/auth.ts b/packages/zitadel-core/src/auth.ts new file mode 100644 index 00000000000..d059a5d9fd0 --- /dev/null +++ b/packages/zitadel-core/src/auth.ts @@ -0,0 +1,22 @@ +import { CompatServiceDefinition } from "nice-grpc/lib/service-definitions"; +import { createChannel, createClientFactory } from "nice-grpc"; +import { + AuthServiceClient, + AuthServiceDefinition, +} from "./proto/server/zitadel/auth"; +import { ZitadelApp } from "./core"; +import { authMiddleware } from "./middleware"; + +const createClient = ( + definition: CompatServiceDefinition, + accessToken: string +) => { + const channel = createChannel(process.env.ZITADEL_API_URL); + return createClientFactory() + .use(authMiddleware(accessToken)) + .create(definition, channel) as Client; +}; + +export async function getAuth(app?: ZitadelApp): Promise { + return createClient(AuthServiceDefinition, ""); +} diff --git a/packages/zitadel-core/src/core.ts b/packages/zitadel-core/src/core.ts index d2759e2c8a8..0b19d15be20 100644 --- a/packages/zitadel-core/src/core.ts +++ b/packages/zitadel-core/src/core.ts @@ -13,7 +13,9 @@ export interface ZitadelApp { config: ZitadelCoreProps; } -export function initializeApp(config: ZitadelCoreProps): ZitadelApp { +export async function initializeApp( + config: ZitadelCoreProps +): Promise { const app = { config }; return app; } diff --git a/packages/zitadel-core/src/management.ts b/packages/zitadel-core/src/management.ts new file mode 100644 index 00000000000..d6c3a202c1c --- /dev/null +++ b/packages/zitadel-core/src/management.ts @@ -0,0 +1,32 @@ +import { CompatServiceDefinition } from "nice-grpc/lib/service-definitions"; + +import { createChannel, createClientFactory } from "nice-grpc"; +import { + ManagementServiceClient, + ManagementServiceDefinition, +} from "./proto/server/zitadel/management"; + +import { authMiddleware } from "./middleware"; +import { ZitadelApp } from "./core"; + +const createClient = ( + definition: CompatServiceDefinition, + accessToken: string +) => { + const apiUrl = process.env.ZITADEL_API_URL; + + if (!apiUrl) { + throw Error("ZITADEL_API_URL not set"); + } + + const channel = createChannel(process.env.ZITADEL_API_URL); + return createClientFactory() + .use(authMiddleware(accessToken)) + .create(definition, channel) as Client; +}; + +export const getManagement = (app?: ZitadelApp) => + createClient( + ManagementServiceDefinition, + process.env.ZITADEL_ADMIN_TOKEN ?? "" + ); diff --git a/packages/zitadel-core/src/middleware.ts b/packages/zitadel-core/src/middleware.ts new file mode 100644 index 00000000000..e88fd57cbe3 --- /dev/null +++ b/packages/zitadel-core/src/middleware.ts @@ -0,0 +1,14 @@ +import { CallOptions, ClientMiddlewareCall, Metadata } from "nice-grpc"; + +export const authMiddleware = (token: string) => + async function* ( + call: ClientMiddlewareCall, + options: CallOptions + ) { + if (!options.metadata?.has("authorization")) { + options.metadata ??= new Metadata(); + options.metadata?.set("authorization", `Bearer ${token}`); + } + + return yield* call.next(call.request, options); + }; diff --git a/packages/zitadel-core/src/system.ts b/packages/zitadel-core/src/system.ts new file mode 100644 index 00000000000..529271dcfb4 --- /dev/null +++ b/packages/zitadel-core/src/system.ts @@ -0,0 +1,35 @@ +import { CompatServiceDefinition } from "nice-grpc/lib/service-definitions"; +import { importPKCS8, SignJWT } from "jose"; + +import { createChannel, createClientFactory } from "nice-grpc"; +import { + SystemServiceClient, + SystemServiceDefinition, +} from "./proto/server/zitadel/system"; +import { authMiddleware } from "./middleware"; + +const createSystemClient = ( + definition: CompatServiceDefinition, + accessToken: string +) => { + const channel = createChannel(process.env.ZITADEL_SYSTEM_API_URL); + return createClientFactory() + .use(authMiddleware(accessToken)) + .create(definition, channel) as Client; +}; + +export const getSystem = async () => { + const token = await new SignJWT({}) + .setProtectedHeader({ alg: "RS256" }) + .setIssuedAt() + .setExpirationTime("1h") + .setIssuer(process.env.ZITADEL_SYSTEM_API_USERID) + .setSubject(process.env.ZITADEL_SYSTEM_API_USERID) + .setAudience(process.env.ZITADEL_ISSUER) + .sign(await importPKCS8(process.env.ZITADEL_SYSTEM_API_KEY, "RS256")); + + return createSystemClient( + SystemServiceDefinition, + token + ); +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f417ba0a009..a58026c7a12 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -86,7 +86,7 @@ importers: lint-staged: 13.0.3 make-dir-cli: 3.0.0 postcss: 8.4.21 - prettier-plugin-tailwindcss: 0.1.13_prettier@2.7.1 + prettier-plugin-tailwindcss: 0.1.13_prettier@2.8.0 tailwindcss: 3.2.4_postcss@8.4.21 ts-proto: 1.146.0 typescript: 4.8.4 @@ -108,9 +108,14 @@ importers: '@zitadel/tsconfig': workspace:* eslint: ^7.32.0 eslint-config-zitadel: workspace:* + jose: ^4.13.1 + nice-grpc: 2.0.1 ts-proto: ^1.139.0 tsup: ^5.10.1 typescript: ^4.5.3 + dependencies: + jose: 4.13.1 + nice-grpc: 2.0.1 devDependencies: '@zitadel/tsconfig': link:../zitadel-tsconfig eslint: 7.32.0 @@ -4423,6 +4428,10 @@ packages: /isexe/2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + /jose/4.13.1: + resolution: {integrity: sha512-MSJQC5vXco5Br38mzaQKiq9mwt7lwj2eXpgpRyQYNHYt2lq1PjkWa7DLXX0WVcQLE9HhMh3jPiufS7fhJf+CLQ==} + dev: false + /joycon/3.1.1: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} @@ -5381,19 +5390,13 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - /prettier-plugin-tailwindcss/0.1.13_prettier@2.7.1: + /prettier-plugin-tailwindcss/0.1.13_prettier@2.8.0: resolution: {integrity: sha512-/EKQURUrxLu66CMUg4+1LwGdxnz8of7IDvrSLqEtDqhLH61SAlNNUSr90UTvZaemujgl3OH/VHg+fyGltrNixw==} engines: {node: '>=12.17.0'} peerDependencies: prettier: '>=2.2.0' dependencies: - prettier: 2.7.1 - dev: true - - /prettier/2.7.1: - resolution: {integrity: sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==} - engines: {node: '>=10.13.0'} - hasBin: true + prettier: 2.8.0 dev: true /prettier/2.8.0: