Cookie SameSite와 Session 끊김 문제

이슈

특정 메뉴에서 세션이 계속 끊어지는 현상 발생

분석

디버깅 결과 해당 기능에서 외부 API에 요청을 보내고 응답을 받은 후 세션이 끊어지는 것을 확인하였다.
세션은 우리 서버에 저장되어있는데 API 연동과 무슨 관계가 있길래 세션이 끊어진 걸까??
처음엔 이해가 되지 않았다. 이상하다…

앗! 맞다 서버에만 저장되어있는게 아니지.. 사용자를 식별하기 위해서 쿠키를 심어놓은다는 사실을 간과했다.

톰캣에선 세션이 생성될 때 상태를 유지하기 위해 사용자 브라우저에 JSESSIONID란 이름의 쿠키를 저장한다.
확인해보니 API 호출 후에 JSESSIONID 값이 변경되는 현상을 발견할 수 있었다.

jsessionidpicture 1. 쿠키 확인

JSESSIONID

왜 변경되었을까? 먼저 Session과 Cookie의 생성과정을 살펴보자.

session-cookepicture 2. 쿠키생성프로세스

  1. 클라이언트에서 처음 요청을하면 서버에서 세션을 생성하고 요청정보에 JSESSIONID 쿠키값이 없으면 새로 생성하여 Response의 Set-Cookie Header에 추가하여 보낸다.
  2. 브라우저에서는 Set-Cookie에 있는 JSESSIONID를 쿠키에 저장한다.
  3. 다음 요청부터는 브라우저에서 Cookie를 요청정보에 포함하여 보낸다.
  4. 서버에서는 요청해더에 JSESSIONID값을 읽어서 상태를 유지한다.

위 과정을 보면 JSESSIONID가 생성되는 경우는 클라이언트 요청에서 Cookie를 보내지 않았을 때이다.
그래서 API 요청시에 Cookie를 보내지 못하는게 아닐까하는 의심이 들었고 확인해보니 역시나 보내지 않고 있었다.
요청쿠키가 없으니 계속 새로운 세션아이디를 생성했던 것이다.

원인

쿠키를 보내지 못한 원인은 크롬 브라우저의 정책 변경 때문이다.
크롬80버전부터 새로운 쿠키 정책이 적용 되어 Cookie의 SameSite 속성의 기본값이 “None”에서 “Lax”로 변경되었다.
SameSite 속성의 값은 Strict, Lax, None 3가지가 있다.

  • Strict : 도메인이 다를 경우 쿠키를 서버로 전송하지 않는다
  • Lax : link rel, a link, GET 요청과 같은 특정한 경우에만 쿠키를 전송
  • None : 도메인이 달라도 쿠키를 전송, 꼭 secure 옵션과 같이 사용해야함(https만 가능)

SameSite 속성 값이 Lax로 설정되어서 쿠키가 전송되지 못하고 결국 JSESSIONID가 변경되는 불상사가 생기게 된 것이다.

cookie-blockpicture 3. 정책에따른 cookie block

해결

구글 검색을해보니 이미 많은 개발자들이 비슷한 문제를 겪고 있었다.
대부분의 해결방법으로 제시한 것은 쿠키 설정에 sameSite=none secure를 적용하는 것이였다.
하지만 보안상 좋아 보이지 않고 근본적인 해결 방법이 아닌 것 같다.
내가 해결한 방법은 JSESSIONID의 이름을 바꾸는 것이다.
server.xml :
<Context … sessionCookieName=”MYJSESSIONID”/>

SameSite=Lax는 Get요청일 때 쿠키전송이 가능하다고 하니 API 요청을 GET방식으로 할 수 있으면 변경해보는 것도 고려해볼만할 것같다.
직접 적용해보진 않아서 모르겠다 ㅎㅎ

결론

프론트엔드 파이가 점점 커짐에따라 갈수로 브라우저 보안이 강화되는 추세다.
현재 크로미움 엔진 기반 브라우저들이 시장을 장악하고 있어서 다른 브라우저들도 크롬정책을 따라가지 않을까 싶다.
SameSite=None 옵션도 삭제될 예정이라고 하며, CSRF 취약점 때문에라도 다른 도메인과의 쿠키 공유는 웬만하면 하지 않는게 좋겠다.