diff --git a/backend/cmd/server/main.go b/backend/cmd/server/main.go index 1a835f59..f37fcfc9 100644 --- a/backend/cmd/server/main.go +++ b/backend/cmd/server/main.go @@ -226,7 +226,7 @@ func main() { auditHandler := handler.NewAuditHandler(auditRepo) authHandler := handler.NewAuthHandler(redisService, idpProvider, auditRepo) adminHandler := handler.NewAdminHandler() - devHandler := handler.NewDevHandler() + devHandler := handler.NewDevHandler(redisService) tenantHandler := handler.NewTenantHandler(db) kratosAdminService := service.NewKratosAdminService() oryAdminProvider := service.NewOryProvider() diff --git a/backend/internal/handler/dev_handler.go b/backend/internal/handler/dev_handler.go index 1f9ba05a..19e72276 100644 --- a/backend/internal/handler/dev_handler.go +++ b/backend/internal/handler/dev_handler.go @@ -12,11 +12,13 @@ import ( type DevHandler struct { Hydra *service.HydraAdminService + Redis *service.RedisService } -func NewDevHandler() *DevHandler { +func NewDevHandler(redis *service.RedisService) *DevHandler { return &DevHandler{ Hydra: service.NewHydraAdminService(), + Redis: redis, } } @@ -102,7 +104,7 @@ func (h *DevHandler) ListClients(c *fiber.Ctx) error { items := make([]clientSummary, 0, len(clients)) for _, client := range clients { - items = append(items, mapClientSummary(client)) + items = append(items, h.mapClientSummary(client)) } return c.JSON(clientListResponse{ @@ -126,7 +128,7 @@ func (h *DevHandler) GetClient(c *fiber.Ctx) error { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()}) } - summary := mapClientSummary(*client) + summary := h.mapClientSummary(*client) return c.JSON(clientDetailResponse{ Client: summary, Endpoints: clientEndpoints{ @@ -165,7 +167,7 @@ func (h *DevHandler) UpdateClientStatus(c *fiber.Ctx) error { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()}) } - summary := mapClientSummary(*updated) + summary := h.mapClientSummary(*updated) return c.JSON(clientDetailResponse{ Client: summary, Endpoints: clientEndpoints{ @@ -251,9 +253,14 @@ func (h *DevHandler) CreateClient(c *fiber.Ctx) error { } created.Metadata["client_secret"] = created.ClientSecret _, _ = h.Hydra.UpdateClient(c.Context(), created.ClientID, *created) + + // Also store in Redis if available + if h.Redis != nil { + _ = h.Redis.Set("client_secret:"+created.ClientID, created.ClientSecret, 0) + } } - summary := mapClientSummary(*created) + summary := h.mapClientSummary(*created) return c.Status(fiber.StatusCreated).JSON(clientDetailResponse{ Client: summary, Endpoints: clientEndpoints{ @@ -341,7 +348,7 @@ func (h *DevHandler) UpdateClient(c *fiber.Ctx) error { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()}) } - summary := mapClientSummary(*updatedClient) + summary := h.mapClientSummary(*updatedClient) return c.JSON(clientDetailResponse{ Client: summary, Endpoints: clientEndpoints{ @@ -367,6 +374,11 @@ func (h *DevHandler) DeleteClient(c *fiber.Ctx) error { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()}) } + // Clean up Redis + if h.Redis != nil { + _ = h.Redis.Delete("client_secret:" + clientID) + } + return c.SendStatus(fiber.StatusNoContent) } @@ -416,7 +428,7 @@ func (h *DevHandler) RevokeConsents(c *fiber.Ctx) error { return c.SendStatus(fiber.StatusNoContent) } -func mapClientSummary(client service.HydraClient) clientSummary { +func (h *DevHandler) mapClientSummary(client service.HydraClient) clientSummary { status := "active" if client.Metadata != nil { if value, ok := client.Metadata["status"].(string); ok && strings.ToLower(value) == "inactive" { @@ -436,6 +448,20 @@ func mapClientSummary(client service.HydraClient) clientSummary { scopes := strings.Fields(client.Scope) + clientSecret := client.ClientSecret + // 1. Check Metadata (Legacy/Fallback) + if clientSecret == "" && client.Metadata != nil { + if val, ok := client.Metadata["client_secret"].(string); ok { + clientSecret = val + } + } + // 2. Check Redis (New) + if clientSecret == "" && h.Redis != nil { + if val, err := h.Redis.Get("client_secret:" + client.ClientID); err == nil && val != "" { + clientSecret = val + } + } + return clientSummary{ ID: client.ClientID, Name: name, @@ -443,7 +469,7 @@ func mapClientSummary(client service.HydraClient) clientSummary { Status: status, RedirectURIs: client.RedirectURIs, Scopes: scopes, - ClientSecret: client.ClientSecret, + ClientSecret: clientSecret, Metadata: client.Metadata, } } diff --git a/compose.ory.yaml b/compose.ory.yaml index 878aa29f..2b97f4c9 100644 --- a/compose.ory.yaml +++ b/compose.ory.yaml @@ -160,6 +160,7 @@ services: - "4457:4455" # Proxy environment: - APP_ENV=${APP_ENV:-development} + - LOG_LEVEL=debug volumes: - ./docker/ory/oathkeeper:/etc/config/oathkeeper - ./docker/ory/oathkeeper/logs:/var/log/oathkeeper diff --git a/devfront/src/app/routes.tsx b/devfront/src/app/routes.tsx index b30cb04c..0bbba406 100644 --- a/devfront/src/app/routes.tsx +++ b/devfront/src/app/routes.tsx @@ -4,7 +4,6 @@ import ClientConsentsPage from "../features/clients/ClientConsentsPage"; import ClientDetailsPage from "../features/clients/ClientDetailsPage"; import ClientGeneralPage from "../features/clients/ClientGeneralPage"; import ClientsPage from "../features/clients/ClientsPage"; -import { ClientFederationPage } from "../features/clients/routes/ClientFederationPage"; export const router = createBrowserRouter( [ @@ -18,7 +17,6 @@ export const router = createBrowserRouter( { path: "clients/:id", element: }, { path: "clients/:id/consents", element: }, { path: "clients/:id/settings", element: }, - { path: "clients/:id/federation", element: }, ], }, ], diff --git a/devfront/src/features/clients/ClientConsentsPage.tsx b/devfront/src/features/clients/ClientConsentsPage.tsx index 36aa843d..d21349db 100644 --- a/devfront/src/features/clients/ClientConsentsPage.tsx +++ b/devfront/src/features/clients/ClientConsentsPage.tsx @@ -120,12 +120,6 @@ function ClientConsentsPage() { > Settings - - Federation - diff --git a/devfront/src/features/clients/ClientDetailsPage.tsx b/devfront/src/features/clients/ClientDetailsPage.tsx index 96baf9f8..dcecfbae 100644 --- a/devfront/src/features/clients/ClientDetailsPage.tsx +++ b/devfront/src/features/clients/ClientDetailsPage.tsx @@ -130,12 +130,6 @@ function ClientDetailsPage() { > Settings - - Federation - diff --git a/devfront/src/features/clients/ClientGeneralPage.tsx b/devfront/src/features/clients/ClientGeneralPage.tsx index 8495d475..d3be16b7 100644 --- a/devfront/src/features/clients/ClientGeneralPage.tsx +++ b/devfront/src/features/clients/ClientGeneralPage.tsx @@ -154,7 +154,6 @@ function ClientGeneralPage() { Connection Consent & Users Settings - Federation )} diff --git a/docker-compose.yaml b/docker-compose.yaml index 981831c9..c800c35e 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -31,7 +31,12 @@ services: ports: - "${BACKEND_PORT:-3000}:3000" depends_on: - - infra_check + postgres: + condition: service_healthy + redis: + condition: service_started + clickhouse: + condition: service_started networks: - baron_net - ory-net diff --git a/docker/ory/oathkeeper/entrypoint.sh b/docker/ory/oathkeeper/entrypoint.sh index 506af8cd..fe15ce6a 100755 --- a/docker/ory/oathkeeper/entrypoint.sh +++ b/docker/ory/oathkeeper/entrypoint.sh @@ -24,7 +24,12 @@ if [ ! -f "$RULES_FILE" ]; then echo "[oathkeeper] rules file not found: $RULES_FILE" exit 1 fi -cp "$RULES_FILE" "$RULES_ACTIVE" + +# Remove existing active rules file to prevent overwrite issues (File exists/Permission denied) +if [ -f "$RULES_ACTIVE" ]; then + rm -f "$RULES_ACTIVE" || echo "[oathkeeper] Warning: Failed to remove existing rules.active.json" +fi +cp -f "$RULES_FILE" "$RULES_ACTIVE" || echo "[oathkeeper] Warning: Failed to copy rules file. Using existing if present." LOG_DIR="/var/log/oathkeeper" LOG_FILE="${LOG_DIR}/access.log" diff --git a/docker/ory/oathkeeper/oathkeeper.yml b/docker/ory/oathkeeper/oathkeeper.yml old mode 100644 new mode 100755 diff --git a/docker/ory/oathkeeper/rules.active.json b/docker/ory/oathkeeper/rules.active.json old mode 100644 new mode 100755 index e02c3382..e65e9d51 --- a/docker/ory/oathkeeper/rules.active.json +++ b/docker/ory/oathkeeper/rules.active.json @@ -1,92 +1,114 @@ [ { "id": "public-health", - "description": "공개 헬스체크", + "description": "공개 헬스체크 (STAGE 도메인)", "match": { - "url": "http://<.*>/health", + "url": "<.*>://sso-test.hmac.kr/health", "methods": ["GET"] }, "upstream": { "url": "http://baron_backend:3000" }, - "authenticators": [ - { "handler": "noop" } - ], + "authenticators": [{ "handler": "noop" }], "authorizer": { "handler": "allow" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] }, { "id": "public-preflight", - "description": "CORS preflight", + "description": "CORS preflight (STAGE 도메인)", "match": { - "url": "http://<.*>/api/v1/<.*>", + "url": "<.*>://sso-test.hmac.kr/api/v1/<.*>", "methods": ["OPTIONS"] }, "upstream": { "url": "http://baron_backend:3000" }, - "authenticators": [ - { "handler": "noop" } - ], + "authenticators": [{ "handler": "noop" }], "authorizer": { "handler": "allow" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] }, { "id": "public-auth", - "description": "인증/회원가입 등 공개 엔드포인트", + "description": "인증/회원가입 등 공개 엔드포인트 (STAGE 도메인)", "match": { - "url": "http://<.*>/api/v1/auth/<.*>", + "url": "<.*>://sso-test.hmac.kr/api/v1/auth/<.*>", "methods": ["GET", "POST", "OPTIONS"] }, "upstream": { "url": "http://baron_backend:3000" }, - "authenticators": [ - { "handler": "noop" } - ], + "authenticators": [{ "handler": "noop" }], "authorizer": { "handler": "allow" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] }, { "id": "backend-command", "description": "Command 요청은 Backend로 전달 (Audit 강제)", "match": { - "url": "http://<.*>/api/v1/<.*>", + "url": "<.*>://sso-test.hmac.kr/api/v1/<.*>", "methods": ["POST", "PUT", "PATCH", "DELETE"] }, "upstream": { "url": "http://baron_backend:3000" }, - "authenticators": [ - { "handler": "cookie_session" } - ], + "authenticators": [{ "handler": "cookie_session" }], "authorizer": { "handler": "remote_json" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] }, { "id": "backend-query", "description": "Backend Query (admin/dev 포함)", "match": { - "url": "http://<.*>/api/v1/<.*>", + "url": "<.*>://sso-test.hmac.kr/api/v1/<.*>", "methods": ["GET"] }, "upstream": { "url": "http://baron_backend:3000" }, - "authenticators": [ - { "handler": "cookie_session" } - ], + "authenticators": [{ "handler": "cookie_session" }], "authorizer": { "handler": "remote_json" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] + }, + { + "id": "hydra-well-known", + "description": "Hydra OIDC Discovery & JWKS", + "match": { + "url": "<.*>://sso-test.hmac.kr/.well-known/<.*>", + "methods": ["GET", "OPTIONS"] + }, + "upstream": { + "url": "http://hydra:4444" + }, + "authenticators": [{ "handler": "noop" }], + "authorizer": { "handler": "allow" }, + "mutators": [{ "handler": "noop" }] + }, + { + "id": "hydra-oauth2", + "description": "Hydra OAuth2 Endpoints", + "match": { + "url": "<.*>://sso-test.hmac.kr/oauth2/<.*>", + "methods": ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"] + }, + "upstream": { + "url": "http://hydra:4444" + }, + "authenticators": [{ "handler": "noop" }], + "authorizer": { "handler": "allow" }, + "mutators": [{ "handler": "noop" }] + }, + { + "id": "hydra-userinfo", + "description": "Hydra Userinfo", + "match": { + "url": "<.*>://sso-test.hmac.kr/userinfo", + "methods": ["GET", "POST", "OPTIONS"] + }, + "upstream": { + "url": "http://hydra:4444" + }, + "authenticators": [{ "handler": "noop" }], + "authorizer": { "handler": "allow" }, + "mutators": [{ "handler": "noop" }] } -] +] \ No newline at end of file diff --git a/docker/ory/oathkeeper/rules.draft.json b/docker/ory/oathkeeper/rules.draft.json old mode 100644 new mode 100755 index 835689ec..95c387f5 --- a/docker/ory/oathkeeper/rules.draft.json +++ b/docker/ory/oathkeeper/rules.draft.json @@ -9,13 +9,9 @@ "upstream": { "url": "http://baron_backend:3000" }, - "authenticators": [ - { "handler": "noop" } - ], + "authenticators": [{ "handler": "noop" }], "authorizer": { "handler": "allow" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] }, { "id": "public-auth", @@ -27,13 +23,9 @@ "upstream": { "url": "http://baron_backend:3000" }, - "authenticators": [ - { "handler": "noop" } - ], + "authenticators": [{ "handler": "noop" }], "authorizer": { "handler": "allow" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] }, { "id": "backend-command", @@ -45,13 +37,9 @@ "upstream": { "url": "http://baron_backend:3000" }, - "authenticators": [ - { "handler": "cookie_session" } - ], + "authenticators": [{ "handler": "cookie_session" }], "authorizer": { "handler": "remote_json" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] }, { "id": "backend-query", @@ -63,13 +51,9 @@ "upstream": { "url": "http://baron_backend:3000" }, - "authenticators": [ - { "handler": "cookie_session" } - ], + "authenticators": [{ "handler": "cookie_session" }], "authorizer": { "handler": "remote_json" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] }, { "id": "kratos-public", @@ -82,13 +66,9 @@ "url": "http://kratos:4433", "strip_path": "/kratos" }, - "authenticators": [ - { "handler": "noop" } - ], + "authenticators": [{ "handler": "noop" }], "authorizer": { "handler": "allow" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] }, { "id": "hydra-public", @@ -101,12 +81,8 @@ "url": "http://hydra:4444", "strip_path": "/hydra" }, - "authenticators": [ - { "handler": "noop" } - ], + "authenticators": [{ "handler": "noop" }], "authorizer": { "handler": "allow" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] } ] diff --git a/docker/ory/oathkeeper/rules.json b/docker/ory/oathkeeper/rules.json old mode 100644 new mode 100755 index e02c3382..e65e9d51 --- a/docker/ory/oathkeeper/rules.json +++ b/docker/ory/oathkeeper/rules.json @@ -1,92 +1,114 @@ [ { "id": "public-health", - "description": "공개 헬스체크", + "description": "공개 헬스체크 (STAGE 도메인)", "match": { - "url": "http://<.*>/health", + "url": "<.*>://sso-test.hmac.kr/health", "methods": ["GET"] }, "upstream": { "url": "http://baron_backend:3000" }, - "authenticators": [ - { "handler": "noop" } - ], + "authenticators": [{ "handler": "noop" }], "authorizer": { "handler": "allow" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] }, { "id": "public-preflight", - "description": "CORS preflight", + "description": "CORS preflight (STAGE 도메인)", "match": { - "url": "http://<.*>/api/v1/<.*>", + "url": "<.*>://sso-test.hmac.kr/api/v1/<.*>", "methods": ["OPTIONS"] }, "upstream": { "url": "http://baron_backend:3000" }, - "authenticators": [ - { "handler": "noop" } - ], + "authenticators": [{ "handler": "noop" }], "authorizer": { "handler": "allow" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] }, { "id": "public-auth", - "description": "인증/회원가입 등 공개 엔드포인트", + "description": "인증/회원가입 등 공개 엔드포인트 (STAGE 도메인)", "match": { - "url": "http://<.*>/api/v1/auth/<.*>", + "url": "<.*>://sso-test.hmac.kr/api/v1/auth/<.*>", "methods": ["GET", "POST", "OPTIONS"] }, "upstream": { "url": "http://baron_backend:3000" }, - "authenticators": [ - { "handler": "noop" } - ], + "authenticators": [{ "handler": "noop" }], "authorizer": { "handler": "allow" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] }, { "id": "backend-command", "description": "Command 요청은 Backend로 전달 (Audit 강제)", "match": { - "url": "http://<.*>/api/v1/<.*>", + "url": "<.*>://sso-test.hmac.kr/api/v1/<.*>", "methods": ["POST", "PUT", "PATCH", "DELETE"] }, "upstream": { "url": "http://baron_backend:3000" }, - "authenticators": [ - { "handler": "cookie_session" } - ], + "authenticators": [{ "handler": "cookie_session" }], "authorizer": { "handler": "remote_json" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] }, { "id": "backend-query", "description": "Backend Query (admin/dev 포함)", "match": { - "url": "http://<.*>/api/v1/<.*>", + "url": "<.*>://sso-test.hmac.kr/api/v1/<.*>", "methods": ["GET"] }, "upstream": { "url": "http://baron_backend:3000" }, - "authenticators": [ - { "handler": "cookie_session" } - ], + "authenticators": [{ "handler": "cookie_session" }], "authorizer": { "handler": "remote_json" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] + }, + { + "id": "hydra-well-known", + "description": "Hydra OIDC Discovery & JWKS", + "match": { + "url": "<.*>://sso-test.hmac.kr/.well-known/<.*>", + "methods": ["GET", "OPTIONS"] + }, + "upstream": { + "url": "http://hydra:4444" + }, + "authenticators": [{ "handler": "noop" }], + "authorizer": { "handler": "allow" }, + "mutators": [{ "handler": "noop" }] + }, + { + "id": "hydra-oauth2", + "description": "Hydra OAuth2 Endpoints", + "match": { + "url": "<.*>://sso-test.hmac.kr/oauth2/<.*>", + "methods": ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"] + }, + "upstream": { + "url": "http://hydra:4444" + }, + "authenticators": [{ "handler": "noop" }], + "authorizer": { "handler": "allow" }, + "mutators": [{ "handler": "noop" }] + }, + { + "id": "hydra-userinfo", + "description": "Hydra Userinfo", + "match": { + "url": "<.*>://sso-test.hmac.kr/userinfo", + "methods": ["GET", "POST", "OPTIONS"] + }, + "upstream": { + "url": "http://hydra:4444" + }, + "authenticators": [{ "handler": "noop" }], + "authorizer": { "handler": "allow" }, + "mutators": [{ "handler": "noop" }] } -] +] \ No newline at end of file diff --git a/docker/ory/oathkeeper/rules.prod.json b/docker/ory/oathkeeper/rules.prod.json old mode 100644 new mode 100755 index d6537966..ef5524d5 --- a/docker/ory/oathkeeper/rules.prod.json +++ b/docker/ory/oathkeeper/rules.prod.json @@ -9,13 +9,9 @@ "upstream": { "url": "http://baron_backend:3000" }, - "authenticators": [ - { "handler": "noop" } - ], + "authenticators": [{ "handler": "noop" }], "authorizer": { "handler": "allow" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] }, { "id": "public-preflight", @@ -27,13 +23,9 @@ "upstream": { "url": "http://baron_backend:3000" }, - "authenticators": [ - { "handler": "noop" } - ], + "authenticators": [{ "handler": "noop" }], "authorizer": { "handler": "allow" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] }, { "id": "public-auth", @@ -45,13 +37,9 @@ "upstream": { "url": "http://baron_backend:3000" }, - "authenticators": [ - { "handler": "noop" } - ], + "authenticators": [{ "handler": "noop" }], "authorizer": { "handler": "allow" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] }, { "id": "backend-command", @@ -63,13 +51,9 @@ "upstream": { "url": "http://baron_backend:3000" }, - "authenticators": [ - { "handler": "cookie_session" } - ], + "authenticators": [{ "handler": "cookie_session" }], "authorizer": { "handler": "remote_json" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] }, { "id": "backend-query", @@ -81,12 +65,8 @@ "upstream": { "url": "http://baron_backend:3000" }, - "authenticators": [ - { "handler": "cookie_session" } - ], + "authenticators": [{ "handler": "cookie_session" }], "authorizer": { "handler": "remote_json" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] } ] diff --git a/docker/ory/oathkeeper/rules.stage.json b/docker/ory/oathkeeper/rules.stage.json old mode 100644 new mode 100755 index 3dabd9a0..e65e9d51 --- a/docker/ory/oathkeeper/rules.stage.json +++ b/docker/ory/oathkeeper/rules.stage.json @@ -3,90 +3,112 @@ "id": "public-health", "description": "공개 헬스체크 (STAGE 도메인)", "match": { - "url": "https://sso.hmac.kr/health", + "url": "<.*>://sso-test.hmac.kr/health", "methods": ["GET"] }, "upstream": { "url": "http://baron_backend:3000" }, - "authenticators": [ - { "handler": "noop" } - ], + "authenticators": [{ "handler": "noop" }], "authorizer": { "handler": "allow" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] }, { "id": "public-preflight", "description": "CORS preflight (STAGE 도메인)", "match": { - "url": "https://sso.hmac.kr/api/v1/<.*>", + "url": "<.*>://sso-test.hmac.kr/api/v1/<.*>", "methods": ["OPTIONS"] }, "upstream": { "url": "http://baron_backend:3000" }, - "authenticators": [ - { "handler": "noop" } - ], + "authenticators": [{ "handler": "noop" }], "authorizer": { "handler": "allow" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] }, { "id": "public-auth", "description": "인증/회원가입 등 공개 엔드포인트 (STAGE 도메인)", "match": { - "url": "https://sso.hmac.kr/api/v1/auth/<.*>", + "url": "<.*>://sso-test.hmac.kr/api/v1/auth/<.*>", "methods": ["GET", "POST", "OPTIONS"] }, "upstream": { "url": "http://baron_backend:3000" }, - "authenticators": [ - { "handler": "noop" } - ], + "authenticators": [{ "handler": "noop" }], "authorizer": { "handler": "allow" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] }, { "id": "backend-command", "description": "Command 요청은 Backend로 전달 (Audit 강제)", "match": { - "url": "https://sso.hmac.kr/api/v1/<.*>", + "url": "<.*>://sso-test.hmac.kr/api/v1/<.*>", "methods": ["POST", "PUT", "PATCH", "DELETE"] }, "upstream": { "url": "http://baron_backend:3000" }, - "authenticators": [ - { "handler": "cookie_session" } - ], + "authenticators": [{ "handler": "cookie_session" }], "authorizer": { "handler": "remote_json" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] }, { "id": "backend-query", "description": "Backend Query (admin/dev 포함)", "match": { - "url": "https://sso.hmac.kr/api/v1/<.*>", + "url": "<.*>://sso-test.hmac.kr/api/v1/<.*>", "methods": ["GET"] }, "upstream": { "url": "http://baron_backend:3000" }, - "authenticators": [ - { "handler": "cookie_session" } - ], + "authenticators": [{ "handler": "cookie_session" }], "authorizer": { "handler": "remote_json" }, - "mutators": [ - { "handler": "noop" } - ] + "mutators": [{ "handler": "noop" }] + }, + { + "id": "hydra-well-known", + "description": "Hydra OIDC Discovery & JWKS", + "match": { + "url": "<.*>://sso-test.hmac.kr/.well-known/<.*>", + "methods": ["GET", "OPTIONS"] + }, + "upstream": { + "url": "http://hydra:4444" + }, + "authenticators": [{ "handler": "noop" }], + "authorizer": { "handler": "allow" }, + "mutators": [{ "handler": "noop" }] + }, + { + "id": "hydra-oauth2", + "description": "Hydra OAuth2 Endpoints", + "match": { + "url": "<.*>://sso-test.hmac.kr/oauth2/<.*>", + "methods": ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"] + }, + "upstream": { + "url": "http://hydra:4444" + }, + "authenticators": [{ "handler": "noop" }], + "authorizer": { "handler": "allow" }, + "mutators": [{ "handler": "noop" }] + }, + { + "id": "hydra-userinfo", + "description": "Hydra Userinfo", + "match": { + "url": "<.*>://sso-test.hmac.kr/userinfo", + "methods": ["GET", "POST", "OPTIONS"] + }, + "upstream": { + "url": "http://hydra:4444" + }, + "authenticators": [{ "handler": "noop" }], + "authorizer": { "handler": "allow" }, + "mutators": [{ "handler": "noop" }] } -] +] \ No newline at end of file diff --git a/userfront/nginx.conf b/userfront/nginx.conf index e57c9eb5..a84a609c 100644 --- a/userfront/nginx.conf +++ b/userfront/nginx.conf @@ -26,10 +26,39 @@ server { error_log /dev/stderr warn; access_log /var/log/nginx/access.log json_combined; - # --- UserFront 정적 파일 --- + # --- Backend API Proxy --- + location /api { + proxy_pass http://baron_backend:3000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + # --- Ory Stack Proxy (via Oathkeeper) --- + # Kratos Public API + location /auth { + proxy_pass http://oathkeeper:4455; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + # Hydra Public API (Rewrite /oidc/... to /...) + location /oidc { + rewrite ^/oidc/(.*)$ /$1 break; + proxy_pass http://oathkeeper:4455; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + # --- UserFront Static Files --- location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; } -} +} \ No newline at end of file