diff --git a/backend/auth/jwt.go b/backend/auth/jwt.go index 5c1c769..b44a46d 100644 --- a/backend/auth/jwt.go +++ b/backend/auth/jwt.go @@ -23,7 +23,7 @@ var TokenAuth *jwtauth.JWTAuth type AuthResponse struct { Token string `json:"token"` JTI string `json:"jti"` - RefreshToken string `json:"refreshToken,omitempty"` + RefreshToken string `json:"-"` } // generateJTI generates a UUID v4 string using crypto/rand diff --git a/backend/handlers/auth/auth_test.go b/backend/handlers/auth/auth_test.go index 4803a7f..584f27c 100644 --- a/backend/handlers/auth/auth_test.go +++ b/backend/handlers/auth/auth_test.go @@ -1747,9 +1747,9 @@ func TestJTI_Revocation_PostgreSQL(t *testing.T) { // Login Response Field Tests (new from security pass) // ============================================================================= -// TestLogin_ResponseIncludesRefreshToken verifies the login response -// includes a refreshToken field alongside the JWT. -func TestLogin_ResponseIncludesRefreshToken(t *testing.T) { +// TestLogin_ResponseOmitsRefreshToken verifies the login response +// does not include refreshToken (G117 — 90-day credential excluded from JSON). +func TestLogin_ResponseOmitsRefreshToken(t *testing.T) { ctx, tx := resetTestData(t) handler := http.HandlerFunc(LoginHandler) @@ -1771,6 +1771,10 @@ func TestLogin_ResponseIncludesRefreshToken(t *testing.T) { t.Fatalf("expected 200, got %d. body: %s", w.Code, w.Body.String()) } + if strings.Contains(w.Body.String(), "refreshToken") { + t.Error("login response should NOT contain refreshToken (G117)") + } + var resp struct { Token string `json:"token"` JTI string `json:"jti"` @@ -1786,8 +1790,8 @@ func TestLogin_ResponseIncludesRefreshToken(t *testing.T) { if resp.JTI == "" { t.Error("expected non-empty jti") } - if resp.RefreshToken == "" { - t.Error("expected non-empty refreshToken in login response") + if resp.RefreshToken != "" { + t.Error("refreshToken should be excluded from JSON response (G117)") } }