Files
llm-wiki/raw/interviews/jwt-resource-server-fine-grained-error-classification-2026-06-08.md
T

3.2 KiB

title, source_type, status, related_branches, related_projects, tags, created, status_label
title source_type status related_branches related_projects tags created status_label
interview-prep / jwt-resource-server-fine-grained-error-classification interview-prep raw
feature-security-operational-baseline
ca-skeleton
interview-prep
ca-skeleton
security
jwt
spring-security
error-handling
2026-06-08 collecting

interview-prep: jwt-resource-server-fine-grained-error-classification

Layer: raw/interviews/ — 면접 질문 원본 수집. 다듬은 답변은 /interviewizewiki/interview/.

Parent / 부모

질문 / Question

  • 질문 원문: JWT 인증 실패를 401 하나로 뭉개지 않고, 운영자가 missing/expired/signature/issuer/audience/unknown-kid 를 구분할 수 있게 어떻게 구현했나요? 클라이언트에는 무엇을 노출했나요?
  • 출처: 예상 질문 (실제 면접 아님).

질문 의도 추론 / Why this question

  • 핵심 평가 대상:
    • Spring Security resource server 의 실패 처리 위치 이해 — bearer 토큰 검증 실패는 BearerTokenAuthenticationFilter/ExceptionTranslationFilterAuthenticationEntryPoint 로 보내며 @RestControllerAdvice도달하지 않는다. 그래서 fine-grained 분류는 EntryPoint/AccessDeniedHandler 에 있어야 한다.
    • 보안 응답의 과노출 방지 — 클라이언트엔 generic message(Authentication failed)만, 내부엔 분류 code. issuer/audience/token 값을 응답·로그에 흘리지 않기.
    • 표준 정합 — 401 은 WWW-Authenticate MUST(RFC 9110 §15.5.2), transient(kid/jwks)엔 Retry-After.
  • 함정:
    • "@RestControllerAdvice 에서 AuthenticationException 잡으면 된다" — filter-layer 실패는 거기 안 온다.
    • exception → code 매핑을 message 문자열 heuristic 에 의존하는 것의 fragility 를 인정 안 함.
    • clock skew 를 default 에 맡기고 "Spring 이 알아서" — 버전 업 시 silent drift.
  • 후속 질문:
    • JwtValidationExceptionBadJwtException 의 차이, 각각 어떤 실패인가?
    • unknown kid 를 왜 retryable=true + Retry-After 로 두나? (rotation 중 JWKS refresh 로 해소)
    • clock skew 60s 를 명시 설정한 이유? (default 의존 시 drift)
    • 다중 audience/validator 동시 실패 시 어떤 code 를 우선하나?

답변 재료 / Raw answer material

  • 구현: SecurityErrorClassifier(exception graph + validator/Nimbus message heuristic, 우선순위 expired>issuer>audience), EnvelopeAuthenticationEntryPoint/EnvelopeAccessDeniedHandler(공통 AuthErrorResponseWriter → Envelope JSON), JwtDecoderConfig(SupplierJwtDecoder 로 lazy 60s clock skew + issuer + audience validator).
  • 12 code 는 docs/registries/error-codes.yaml SSOT 와 OperationalError enum 일치(status/category/retryable).
  • redaction: 응답 body 는 generic message, 로그는 code/category/method/path 만 — token(eyJ...) 미노출. contract test 로 강제.
  • 한계(솔직): message 문자열 heuristic 은 Spring/Nimbus 버전 메시지 변경에 취약 → unmapped 는 generic 401 fallback(절대 500 아님). 실 IdP 통합 테스트는 미수행(prod-verified 아님).