이 내용에 대해 쓰는 이유는 토큰이 URL상 노출되어 어떤 원리가 적용되는지 공부하고자 씀
HTTP : 웹에서 클라이언트와 서버가 데이터를 주고받기 위해 사용하는 가장 기초적인 약속(프로토콜) -> 요청과 응답이 존재
구조
: 해더(여기에 토큰), 바디(데이터-JSON,HTML), URL
REST API :HTTP의 장점을 최대한 활용하여 자원중심으로 설계를 관리하는 아키텍쳐 스타일
EventSource : 브라우저에 내장된 표준 API. 서버가 푸시하는 SSE를 클라이언트에서 수신하기 위해 사용하는 전용 수신기 역할
EventSource는 헤더 설정이 불가능함. HTTP 헤더를 수정할 수 있는 옵션이 아예 없음. 애초에 설계를 이렇게 하였음. 인증을 위해 JWT 토큰을 보내야 하는데 헤더(Authorization)를 못쓰니 서버가 읽을 수 있는 공간인 URL 쿼리 파라미터(token = axf...)에 실어 보냄
/subscribe 하나에서만 하면 문제가 최소겠지만, 그 전 코드에선 모든 요청에 쿼리 파라미터 token을 읽으려 시도함
AI를 도입하며 가장 조심해야 되는게 이런 부분임. 보안 관련 조심하라고 말을 해도 듣질 않음.
이럴 땐 보완 관련 체크리스트를 세심히 만들어서 체크하라고 해야함.
암튼 전체 바꿔버린 이유가 SSE가 헤더를 못바꾼다고 해서 바꾼거 같은데, subscribe 할 때만 헤더에 넣어줌으로써 토큰 노출을 최소화 함
문제 1. 서버 로그에 찍힘
: Nginx, Apache, Tomcat 같은 웹 서버는 모든 요청 URL을 로그에 남김. 공격자가 서버 로그만 탈취해도 많은 사용자의 토큰을 얻게 됨
문제 2. 브라우저 히스토리
: 사용자의 브라우저 방문 기록에 토큰이 포함된 URL이 그대로 남음. 공용 PC를 사용한다면 다음 사람이 내 계정을 탈취할 수 있음.
문제 3. Referer 헤더 유출
: 사용자가 해당 페이지에서 외부 링크를 클릭해 다른 사이트로 이동할 때, 브라우저는 이전 페이지의 URL(토큰 포함)을 상대 사이트 서버로 전송
우선 해결책으로는 노출을 최소화 하는 방향으로 갔음
하지만 노출을 최소화 하더라도 어쩄든 노출이 있을 수 밖에 없음. 해당 서비스에서는 돈 관련이나 보안 문제가 크지 않기에 문제가 되지 않을 수 있으나 방어책은 필요함
1. 일회용 티켓 으로 알림 설정하기
- 티켓 요청 (REST API방식<헤더에 토큰 담겨있음>)
: 클라이언트가 헤더에 JWT을 담아POST /api/v1/notification/ticket을 호출함- 티켓 발급
: 서버는 수명이 짧은(10초~30초 - 여유되면 더 줄이고) UUID를 생성해 DB나 Redis에 저장해둠- SSE 연결
: 클라이언트는 EventSource(/subscribe?ticket=티켓번호) 로 접속- 검증 및 폐기
: 서버는 티켓을 확인해 인증을 처리하고 즉시 티켓 삭제2. 서버 로그 마스킹
: 인프라 수준에서 로그 자체를 숨김
-> 서버 하드웨어에 로그는 남지만, 관리자나 해커가 그 로그 파일을 열어봐도 실제 토큰 값은 볼 수 없음
-근본적인 해결이 아님-
1. 데이터가 전송되는 과정(In-flight)이나 클라이언트 측에 남는 흔적은 전혀 보호하지 못한다는 명확한 한계
2. Referer 헤더를 통해 외부 사이트로 토큰이 전달되는 문제는 마스킹으로 해결할 수 없음
3. 로그를 마스킹하면 디버깅이 어려워질수 있음3. 폴리필 라이브러리 사용
: 표준 API의 한계를 우회함
-> 브라우저의 기본 EventSource 대신 fetch-event-source 같은 라이브러리를 사용
-> 내부적으로 fetch를 사용하므로 SSE 연결임에도 헤더에 토큰을 담을 수 있음.
의존성 추가라는 트레이드 오프 (그 외에는 학습이 필요)