나의 프로젝트는 리액트와 express를 사용하였고, JWT 토큰 방식을 사용하여 로그인 인증을 구현했다. Chrome 브라우저에서는 올바르게 쿠키에 토큰이 잘 저장되어 로그인이 성공적이였다.
res
.status(200)
.cookie("token", refresh_token, {
httpOnly: true,
secure: true,
sameSite: "none",
})
그러나, 아이폰과 사파리로 테스트를 해봤더니 토큰이 쿠키에 저장되지 않은 현상이 발생하였다. 그래서 구글링과 테스트 결과 여러가지 단서를 찾을 수 있었다.
Chrome is moving towards a new experience that allows users to choose to browse without third-party cookies.
라는 경고 메세지가 발생하고 있었다.
이 메세지는 Chrome이 서드 파티 쿠키를 중단할 것이라고 말하고 있다.
IOS는 이미 서드 파티 쿠키를 지원하지 않은 상태인 것을 보면 IOS 환경에서 로그인이 되지 않았던 이유가 높은 확률로 서드 파티 쿠키를 지원하지 않아서 라고 추측했다.
삼성 인터넷도 마찬가지로 쿠키가 저장되지 않은 현상을 겪고 있었다. 서드 파티 쿠키를 허용하고 로그인을 시도하였더니 로그인에 성공하였다.
※ 삼성 인터넷 서드파티 쿠키 허용 방법
설정 > 개인정보 보호 현황 > 스마트 추적 방지 사용 안함
따라서 서드파티 쿠키 차단이 문제라는 것을 확신했다.
먼저, 서드 파티 쿠키가 뭔지 간단하게 알아봤는데 퍼스트 파티 쿠키와 서드 파티 쿠키라는 것이 있었다.
같은 도메인 또는 서브 도메인에서 생성된 쿠키를 말한다. cookidge.vercel.app
, api.cookidge.vercel.app
두 서브 도메인 관계에서는 쿠키를 서로 공유할 수 있다.
제 3자의 도메인에서 생성된 쿠키를 말한다. 예를 들어, 프론트 도메인 cookidge.vercel.app
과 백엔드 도메인 cookidge-api.vercel.app
이 존재한다. 백엔드 도메인에서 프론트 도메인에 쿠키를 발급해 줄 때, 서드 파티 쿠키 취급이 된다.
구글링을 통해 여러가지 해결 방법이 존재한다는 것을 알게됐다. 그리고 여러가지 해결 방법들을 수행해봤다.
도메인 속성에 페이지를 등록하면 해결된다는 방법이다. 이 방법은 도움이 되지 않았다.
res
.status(200)
.cookie("token", refresh_token, {
httpOnly: true,
secure: true,
sameSite: "none",
domain: "cookidge.vercel.app"
})
이 방법은 아예 고려하지 않았다. 로그인 기능에 보안을 뺀다는 것은 웹 사이트에 신뢰를 잃는 것이다.
백엔드 서버에서 발급하는 토큰을 퍼스트 파티 쿠키로 저장하는 것이다. 즉 api 서버를 api.domain.com
으로 domain.com
의 하위 도메인으로 지정하여 쿠키를 공유하는데 문제가 없게 하는 방법이다.
커스텀 도메인 구입 방법이 가장 유효한 방법이다. 하지만 내 사이트는 0원으로 개발하는 것을 목표로 하기 때문에, 나는 다음과 같은 경우에 해결 방법을 적용할 것이다.
이러한 문제가 발생하고 해결방법을 찾는 과정도 중요하다. 상황에 맞게 해결 방법을 적용할 것이다. 따라서, Cookidge 0원 프로젝트 컨셉을 좀 더 지켜보고, 도메인을 구입하여 에러를 해결하는 방안을 고민해 볼 것이다.
Proxy
를 통해 해당 문제를 해결했다. 개발 환경에서는 http-proxy-middleware
를 사용하고, 배포 환경에서는 vercel
을 사용했기 때문에 vercel.json
파일을 설정하는 방법으로 해결했다.
간단하게 원리를 파악해 보자면, 중간에 프록시 서버를 두고 프록시 서버가 백엔드랑 통신을 해준다. 그리고 클라이언트는 프록시 서버랑 통신을 하는 것이다.
Client: https://example.com
Server: https://example-api.com
Client(Proxy): https://example.com
네트워크 요청을 할 때, 브라우저는 서버가 아닌 프록시 서버(리액트 서버)로 요청하게 된다. 프록시 서버가 해당 요청을 백엔드와 통신한 후, 클라이언트에 응답해주게 된다.
이렇게 되면, 클라이언트와 프록시 서버는 동일한 origin
을 갖게 되어, cors
에러를 우회할 수 있고, 퍼스트 파티 쿠키로 발급받을 수 있는 것이다.
※
CORS
에러는 보안을 위해 존재하는 것이므로 우리를 위한 것이다. 무조건 우회하려는게 아닌 신뢰할 수 있는 본인의 백엔드 서버의 경우에만Proxy
를 사용하자.