diff --git a/deploy/docker/docker-compose.yml b/deploy/docker/docker-compose.yml
index 3475353..96bd93f 100644
--- a/deploy/docker/docker-compose.yml
+++ b/deploy/docker/docker-compose.yml
@@ -40,6 +40,8 @@ services:
build:
context: ../../packages/gateway
container_name: it0-api-gateway
+ environment:
+ - JWT_SECRET=${JWT_SECRET:-dev-jwt-secret}
ports:
- "18000:8000"
- "18001:8001"
diff --git a/it0-web-admin/src/app/(admin)/layout.tsx b/it0-web-admin/src/app/(admin)/layout.tsx
index def72c8..1f64028 100644
--- a/it0-web-admin/src/app/(admin)/layout.tsx
+++ b/it0-web-admin/src/app/(admin)/layout.tsx
@@ -1,9 +1,25 @@
'use client';
+import { useEffect, useState } from 'react';
+import { useRouter } from 'next/navigation';
import { Sidebar } from '@/presentation/components/layout/sidebar';
import { TopBar } from '@/presentation/components/layout/top-bar';
export default function AdminLayout({ children }: { children: React.ReactNode }) {
+ const router = useRouter();
+ const [ready, setReady] = useState(false);
+
+ useEffect(() => {
+ const token = localStorage.getItem('access_token');
+ if (!token) {
+ router.replace('/login');
+ } else {
+ setReady(true);
+ }
+ }, [router]);
+
+ if (!ready) return null;
+
return (
diff --git a/it0-web-admin/src/app/(auth)/login/page.tsx b/it0-web-admin/src/app/(auth)/login/page.tsx
index 7c6168e..d916a43 100644
--- a/it0-web-admin/src/app/(auth)/login/page.tsx
+++ b/it0-web-admin/src/app/(auth)/login/page.tsx
@@ -23,7 +23,7 @@ export default function LoginPage() {
setError(null);
try {
- const data = await apiClient('/auth/login', {
+ const data = await apiClient('/api/v1/auth/login', {
method: 'POST',
body: { email, password },
});
@@ -32,6 +32,14 @@ export default function LoginPage() {
localStorage.setItem('refresh_token', data.refreshToken);
localStorage.setItem('user', JSON.stringify(data.user));
+ // Decode tenantId from JWT and store as current tenant
+ try {
+ const payload = JSON.parse(atob(data.accessToken.split('.')[1]));
+ if (payload.tenantId) {
+ localStorage.setItem('current_tenant', JSON.stringify({ id: payload.tenantId }));
+ }
+ } catch { /* ignore decode errors */ }
+
router.push('/dashboard');
} catch (err) {
setError(err instanceof Error ? err.message : 'Login failed');
diff --git a/packages/gateway/Dockerfile b/packages/gateway/Dockerfile
index d145b55..16abdf1 100644
--- a/packages/gateway/Dockerfile
+++ b/packages/gateway/Dockerfile
@@ -1,9 +1,13 @@
FROM kong:3.7
-COPY config/kong.yml /etc/kong/kong.yml
+COPY config/kong.yml /etc/kong/kong.yml.tpl
+COPY config/docker-entrypoint.sh /custom-entrypoint.sh
+RUN chmod +x /custom-entrypoint.sh
ENV KONG_DATABASE=off
ENV KONG_DECLARATIVE_CONFIG=/etc/kong/kong.yml
ENV KONG_PROXY_LISTEN=0.0.0.0:8000
ENV KONG_ADMIN_LISTEN=0.0.0.0:8001
ENV KONG_LOG_LEVEL=info
+
+ENTRYPOINT ["/custom-entrypoint.sh"]
diff --git a/packages/gateway/config/docker-entrypoint.sh b/packages/gateway/config/docker-entrypoint.sh
new file mode 100644
index 0000000..c35a1c3
--- /dev/null
+++ b/packages/gateway/config/docker-entrypoint.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+# Substitute JWT_SECRET into Kong declarative config at runtime
+sed "s/\${JWT_SECRET}/${JWT_SECRET:-dev-jwt-secret}/g" /etc/kong/kong.yml.tpl > /etc/kong/kong.yml
+exec /docker-entrypoint.sh kong docker-start
diff --git a/packages/gateway/config/kong.yml b/packages/gateway/config/kong.yml
index 4f3424f..4535a70 100644
--- a/packages/gateway/config/kong.yml
+++ b/packages/gateway/config/kong.yml
@@ -1,5 +1,12 @@
_format_version: "3.0"
+consumers:
+ - username: it0-system
+ jwt_secrets:
+ - key: it0-auth
+ algorithm: HS256
+ secret: "${JWT_SECRET}"
+
services:
- name: auth-service
url: http://auth-service:3001
@@ -24,6 +31,14 @@ services:
- http
- https
+ - name: agent-config-service
+ url: http://agent-service:3002
+ routes:
+ - name: agent-config-routes
+ paths:
+ - /api/v1/agent-config
+ strip_path: false
+
- name: ops-service
url: http://ops-service:3003
routes:
diff --git a/packages/services/auth-service/src/application/services/auth.service.ts b/packages/services/auth-service/src/application/services/auth.service.ts
index 9c825a7..4271af8 100644
--- a/packages/services/auth-service/src/application/services/auth.service.ts
+++ b/packages/services/auth-service/src/application/services/auth.service.ts
@@ -153,7 +153,10 @@ export class AuthService {
roles: user.roles,
};
- const accessToken = this.jwtService.sign(jwtPayload);
+ const accessToken = this.jwtService.sign({
+ ...jwtPayload,
+ kid: 'it0-auth',
+ });
const refreshToken = this.jwtService.sign(
{ sub: user.id, type: 'refresh' },