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' },