flawopen.com/참조/JWT와 HttpOnly 쿠키
localStorage의 JWT와 HttpOnly 쿠키: 무엇이 더 안전한가
많은 웹 애플리케이션에서 서버가 관리하는 세션을 HttpOnly 쿠키로 전달하는 방식은 좋은 기본 선택입니다. JavaScript가 쿠키를 읽을 수 없어 토큰 추출을 줄여 주지만, XSS 자체를 무력화하지는 않습니다. 같은 출처에서 실행되는 삽입 코드는 인증된 요청을 보내고 페이지에서 접근 가능한 데이터를 읽을 수 있습니다.
보안상의 절충
| 저장 / 전송 | XSS 노출 | CSRF 동작 | 폐기 |
|---|---|---|---|
localStorage bearer token | 같은 출처 JavaScript가 읽을 수 있으며 XSS가 토큰을 훔치거나 사용자처럼 동작할 수 있습니다. | 사이트 간 요청에 자동으로 포함되지 않지만 XSS와 클라이언트 측 CSRF 위험은 남습니다. | 폐기 여부를 확인하지 않으면 자체 포함 JWT가 만료까지 유효할 수 있습니다. |
HttpOnly cookie | JavaScript가 쿠키 값을 읽을 수 없지만 XSS가 인증 요청을 보내는 것은 가능합니다. | 쿠키 규칙에 따라 자동 전송됩니다. SameSite는 CSRF 방어의 한 계층일 뿐입니다. | 불투명 세션은 서버에서 무효화할 수 있습니다. JWT 쿠키는 별도 폐기 정책이 필요합니다. |
권장 아키텍처
- ✓세션 식별자를
HttpOnly; Secure; SameSite=Lax쿠키에 저장하세요. - ✓지속적 인증 토큰을
localStorage나sessionStorage에 저장하지 마세요.
토큰 형식, 저장 위치, 세션 상태를 구분하세요
JWT는 토큰 형식이고 localStorage와 쿠키는 브라우저의 저장 및 전송 방식입니다. JWT는 둘 중 어디에나 저장할 수 있습니다. 쿠키의 불투명한 세션 식별자는 보통 서버가 관리하는 상태를 가리킵니다. “JWT냐 쿠키냐”는 동등한 대안 간의 직접 비교가 아닙니다.
각 선택이 바꾸는 점
브라우저는 localStorage 값을 사이트 간 요청에 자동으로 붙이지 않지만, 같은 출처의 XSS는 bearer 토큰을 읽거나 애플리케이션을 통해 동작할 수 있습니다. 쿠키는 브라우저 규칙에 따라 자동 전송됩니다. HttpOnly는 JavaScript에서 값을 숨기지만 삽입 코드가 로그인된 페이지를 사용하는 것은 막지 못합니다. SameSite=Lax는 CSRF 방어의 한 계층이지 완전한 보장은 아닙니다. 안전한 메서드의 최상위 탐색과 same-site 요청도 고려하고, GET으로 상태를 변경하지 말며 적절한 토큰 및/또는 Origin 검증을 적용하세요.
폐기는 저장 위치가 아니라 서버 상태와 토큰 검증에 달려 있습니다. 서버 세션은 기록을 삭제해 무효화할 수 있습니다. 폐기 여부를 확인하지 않으면 자체 포함 JWT가 만료까지 유효할 수 있습니다. 짧은 수명은 그 기간을 줄이지만 없애지는 않습니다.
실무적인 출발점
- ✓자체 웹 앱에서는 적합한 경우 불투명한 서버 측 세션이나 Backend-for-Frontend (BFF)를 우선 고려하세요.
- ✓세션 쿠키에
Secure,HttpOnly, 의도적으로 선택한SameSite,Path=/를 설정하고, 가능하면Domain을 생략하며__Host-접두사를 고려하세요. - ✓위협 모델에 따라 상태 변경 요청에 CSRF 토큰 및/또는 Origin 검증을 적용하고,
GET으로 상태를 변경하지 마세요. - ✓브라우저 JWT가 필요하다면 수명을 짧게 하고 로그아웃/폐기를 정의하며 XSS를 방지하세요. 쿠키 저장은 권한 검사를 대체하지 않습니다.