WEBBOOK CHAPTER

Spring Security 6, 인증에서 운영까지: 12장. 401과 403을 다르게 설계한다

12장. 401과 403을 다르게 설계한다

401은 유효한 인증이 없어서 자격 증명이 필요하다는 뜻이고, 403은 인증은 되었지만 해당 작업이 허용되지 않는다는 뜻이다. 브라우저 form login은 302 redirect가 자연스러울 수 있지만 JSON API가 로그인 HTML을 200으로 받으면 클라이언트가 실패를 오판한다. API chain에는 JSON AuthenticationEntryPointAccessDeniedHandler를 둔다.


{
  "type": "https://contracthub.example/problems/access-denied",
  "title": "Access denied",
  "status": 403,
  "traceId": "01J...",
  "decisionId": "dec_..."
}

응답에는 “OTHER 관리자가 ACME 계약을 노렸다” 같은 내부 정책을 자세히 노출하지 않는다. 사용자에게 필요한 다음 행동과 지원용 ID를 주고, 상세 결정 근거는 접근 통제된 감사 시스템에 둔다. 인증 실패 문구는 존재하는 계정과 없는 계정을 구분하지 않게 통일한다.

클라이언트는 401에서 무한 refresh loop를 만들지 않아야 한다. refresh가 한 번 실패하면 로그인으로 전환하고 원래 요청을 안전하게 보존한다. 403을 token refresh로 해결하려 반복하지 않는다.