diff --git a/backend/internal/domain/headless_jwks_cache.go b/backend/internal/domain/headless_jwks_cache.go index 2c48a5fa..082b69d6 100644 --- a/backend/internal/domain/headless_jwks_cache.go +++ b/backend/internal/domain/headless_jwks_cache.go @@ -3,11 +3,11 @@ package domain import "time" type HeadlessJWKSParsedKey struct { - Kid string `json:"kid,omitempty"` - Kty string `json:"kty,omitempty"` - Use string `json:"use,omitempty"` - Alg string `json:"alg,omitempty"` - NPreview string `json:"nPreview,omitempty"` + Kid string `json:"kid,omitempty"` + Kty string `json:"kty,omitempty"` + Use string `json:"use,omitempty"` + Alg string `json:"alg,omitempty"` + N string `json:"n,omitempty"` } // HeadlessJWKSCacheState는 headless login용 JWKS 캐시 상태와 최근 동기화 결과를 나타냅니다. diff --git a/backend/internal/handler/dev_handler_test.go b/backend/internal/handler/dev_handler_test.go index cd6f2593..c694c35a 100644 --- a/backend/internal/handler/dev_handler_test.go +++ b/backend/internal/handler/dev_handler_test.go @@ -10,7 +10,6 @@ import ( "io" "net/http" "net/http/httptest" - "strings" "testing" "time" @@ -108,14 +107,6 @@ func devTestJWKSFirstKeyString(t *testing.T, jwks map[string]any, field string) return value } -func devTestPreviewValue(value string) string { - value = strings.TrimSpace(value) - if len(value) <= 24 { - return value - } - return value[:12] + "..." + value[len(value)-12:] -} - // --- Tests --- func TestListClients_Success(t *testing.T) { @@ -855,7 +846,7 @@ func TestRefreshHeadlessJWKSCache_ReturnsUpdatedCacheState(t *testing.T) { privateKey, jwks := mustHeadlessRSAJWK(t) _ = privateKey jwksBody, _ := json.Marshal(jwks) - expectedNPreview := devTestPreviewValue(devTestJWKSFirstKeyString(t, jwks, "n")) + expectedN := devTestJWKSFirstKeyString(t, jwks, "n") redisRepo := &devMockRedisRepo{data: map[string]string{}} h := &DevHandler{ Hydra: &service.HydraAdminService{ @@ -908,7 +899,7 @@ func TestRefreshHeadlessJWKSCache_ReturnsUpdatedCacheState(t *testing.T) { assert.Equal(t, "RSA", got.HeadlessJWKSCache.ParsedKeys[0].Kty) assert.Equal(t, "sig", got.HeadlessJWKSCache.ParsedKeys[0].Use) assert.Equal(t, "RS256", got.HeadlessJWKSCache.ParsedKeys[0].Alg) - assert.Equal(t, expectedNPreview, got.HeadlessJWKSCache.ParsedKeys[0].NPreview) + assert.Equal(t, expectedN, got.HeadlessJWKSCache.ParsedKeys[0].N) } } } diff --git a/backend/internal/service/headless_jwks_cache.go b/backend/internal/service/headless_jwks_cache.go index 29078ad4..2413a662 100644 --- a/backend/internal/service/headless_jwks_cache.go +++ b/backend/internal/service/headless_jwks_cache.go @@ -390,24 +390,16 @@ func summarizeHeadlessJWKS(raw string) []domain.HeadlessJWKSParsedKey { parsedKeys := make([]domain.HeadlessJWKSParsedKey, 0, len(document.Keys)) for _, key := range document.Keys { parsedKeys = append(parsedKeys, domain.HeadlessJWKSParsedKey{ - Kid: strings.TrimSpace(key.Kid), - Kty: strings.TrimSpace(key.Kty), - Use: strings.TrimSpace(key.Use), - Alg: strings.TrimSpace(key.Alg), - NPreview: previewHeadlessJWKValue(key.N), + Kid: strings.TrimSpace(key.Kid), + Kty: strings.TrimSpace(key.Kty), + Use: strings.TrimSpace(key.Use), + Alg: strings.TrimSpace(key.Alg), + N: strings.TrimSpace(key.N), }) } return parsedKeys } -func previewHeadlessJWKValue(value string) string { - value = strings.TrimSpace(value) - if len(value) <= 24 { - return value - } - return value[:12] + "..." + value[len(value)-12:] -} - func extractHeadlessKids(keySet *jose.JSONWebKeySet) []string { if keySet == nil { return nil diff --git a/devfront/src/features/clients/ClientGeneralPage.tsx b/devfront/src/features/clients/ClientGeneralPage.tsx index a8db153c..76a93d35 100644 --- a/devfront/src/features/clients/ClientGeneralPage.tsx +++ b/devfront/src/features/clients/ClientGeneralPage.tsx @@ -1313,35 +1313,55 @@ function ClientGeneralPage() {

{currentHeadlessJwksCache.parsedKeys?.length ? ( -
+
{currentHeadlessJwksCache.parsedKeys.map((key, index) => (
-
- - {key.kid || "-"} - - - {key.kty || "-"} - - - {key.use || "-"} - - - {key.alg || "-"} - +
+
+

+ KID +

+

+ {key.kid || "-"} +

+
+
+

+ KTY +

+

+ {key.kty || "-"} +

+
+
+

+ USE +

+

+ {key.use || "-"} +

+
+
+

+ ALG +

+

+ {key.alg || "-"} +

+

{t( "ui.dev.clients.general.public_key.cache.parsed_key_n", - "n Preview", + "N", )}

-

- {key.nPreview || "-"} +

+ {key.n || "-"}

diff --git a/devfront/src/lib/devApi.ts b/devfront/src/lib/devApi.ts index 6fd9faa1..db25ad10 100644 --- a/devfront/src/lib/devApi.ts +++ b/devfront/src/lib/devApi.ts @@ -80,7 +80,7 @@ export type ClientDetailResponse = { kty?: string; use?: string; alg?: string; - nPreview?: string; + n?: string; }>; }; }; diff --git a/devfront/tests/devfront-clients-lifecycle.spec.ts b/devfront/tests/devfront-clients-lifecycle.spec.ts index cd811416..80a0d573 100644 --- a/devfront/tests/devfront-clients-lifecycle.spec.ts +++ b/devfront/tests/devfront-clients-lifecycle.spec.ts @@ -149,8 +149,8 @@ test.describe("DevFront clients lifecycle", () => { kty: "RSA", use: "sig", alg: "RS256", - nPreview: - "voVbHlo_UHkj...Hb8PiTCQ", + n: + "voVbHlo_UHkjtT7Q_8owyjZ2omE8n8mbGlpraZziStHPfe08q_RGiEXO6Pyiz42NVi-Yo0c7qiaqRwB4h9s5phpT2wwcUxnkrQeRhe7BpigInZPzpwq1hsaB2zyhE7zTRCC3hinGtFdVpNzTVKYKGPbXfeEXaRL3P838vi-_iB4IN3WQk_pAakUQvajL2H-vcWSMSNslMGPDZxobqE9MHSWocNXemrcmtCeE7ruUND0qHZOb8k-hHUBqsNoJ63WKdapzGYF6e2qgDRveYrjgOCBigZPi8npN0xStQ0YcrH_RxeTogsdRZ8SuXmLqavryVDnrT8czPkkJ-EHb8PiTCQ", }, ], }, @@ -211,6 +211,7 @@ test.describe("DevFront clients lifecycle", () => { page.getByText(/cached at|캐시됨|last refresh|마지막 갱신/i), ).toBeVisible(); await expect(page.getByText(/Parsed Keys|파싱된 키/i)).toBeVisible(); + await expect(page.getByText(/^KID$/i)).toBeVisible(); await expect(page.getByText("kid-1", { exact: true }).last()).toBeVisible(); await expect( page.getByText(/Allowed algorithms|허용 알고리즘/i), @@ -230,7 +231,10 @@ test.describe("DevFront clients lifecycle", () => { await expect(page.getByText(algorithm, { exact: true }).last()).toBeVisible(); } await expect( - page.getByText("voVbHlo_UHkj...Hb8PiTCQ", { exact: true }), + page.getByText( + "voVbHlo_UHkjtT7Q_8owyjZ2omE8n8mbGlpraZziStHPfe08q_RGiEXO6Pyiz42NVi-Yo0c7qiaqRwB4h9s5phpT2wwcUxnkrQeRhe7BpigInZPzpwq1hsaB2zyhE7zTRCC3hinGtFdVpNzTVKYKGPbXfeEXaRL3P838vi-_iB4IN3WQk_pAakUQvajL2H-vcWSMSNslMGPDZxobqE9MHSWocNXemrcmtCeE7ruUND0qHZOb8k-hHUBqsNoJ63WKdapzGYF6e2qgDRveYrjgOCBigZPi8npN0xStQ0YcrH_RxeTogsdRZ8SuXmLqavryVDnrT8czPkkJ-EHb8PiTCQ", + { exact: true }, + ), ).toBeVisible(); await expect( page.getByRole("button", { name: /refresh|새로고침/i }), diff --git a/devfront/tests/helpers/devfront-fixtures.ts b/devfront/tests/helpers/devfront-fixtures.ts index 491d6629..d3643940 100644 --- a/devfront/tests/helpers/devfront-fixtures.ts +++ b/devfront/tests/helpers/devfront-fixtures.ts @@ -33,7 +33,7 @@ export type Client = { kty?: string; use?: string; alg?: string; - nPreview?: string; + n?: string; }>; }; metadata?: Record;