[ganoverflow/0705] feat-auth: 배포 클라/서버 간 쿠키의 정상적 송수신을 위한 cookie set 설정 추가 (domain, ...samesite)

horiz.d·2023년 7월 4일
0

변경내용

직전 배포수준에서 테스트해본 결과 refresh_token이 응답에 담겨왔으나, 저장은 하지 못한 모습을 확인했습니다.

환경은 SSL이 적용된 https 서버<->클라 간의 배포수준 통신입니다.


해결을 위해, 제가 ai-ght 개인 프로젝트를 하며 서로 다른 도메인 간 어떻게 쿠키를 주고받을 지 고민했던 내용을 반영합니다.

  1. samesite: none 설정 추가 <- 이는 보안을 위해 반드시 secure 설정과 함께 사용되어야 합니다. (개발환경 제외)
  2. domain 설정 추가, 이는 환경변수를 통해 받아옵니다. dev는 localhost, prod에선 .(ourdomain.com)을 통해 서브도메인 모두를 허용하도록 했습니다.
    • 도메인은 COOKIE_DOMAIN이라는 이름의 환경변수로 관리하므로, 배포 인스턴스 서버에 의 환경변수 파일에도 이를 반영했습니다.

  async setCookieWithRefreshToken(res: any, refresh_token: string) {
    const cookieSecure = this.configService.get("COOKIE_SECURE") === "true"; 
    // env파일 별 분기 string -> boolean 변환이요!
    const cookieDomain = this.configService.get("COOKIE_DOMAIN");

    res.cookie("refresh_token", refresh_token, {
      httpOnly: cookieSecure,
      secure: cookieSecure,
      domain: cookieDomain,
      sameSite: "none",
      maxAge: 1000 * 60 * 60 * 24 * 7,
    });

    return res;
  }
  
  ...

쿠키 저장 확인


+ dev환경에서의 samesite 정책 문제 해결

위의 설정을 적용한 이후 로컬의 development환경에서this attempt to set a cookie via a Set-Cookie header was blocked because it had the "SameSite=None" attribute but did not have the "Secure" attribute, which is required in order to use "SameSite=None" 에러를 발생시키며, refresh token 저장 및 변경사항 테스트를 불가능하게 하였다.

이는 이전에 확인해본 적 있는 에러이다.
문제가 되는 부분은 쿠키 설정에서 SameSite 속성이 'None'으로 설정되어 있는데, 이 경우 Secure 속성도 반드시 true로 설정되어야 한다.

SameSite=None은 쿠키가 cross-site 요청에도 전송되어야 함을 의미하며, 이는 보안 상 문제가 될 수 있으므로 HTTPS(즉, Secure=true) 아래에서만 허용된다. 이는 이전의 ai-ght 프로젝트를 진행하며 한번 정리한 적 있는 문제로 구글의 보안 정책을 따르는 조치이다.



따라서, 개발 환경(secure=false)에서 SameSite 속성을 'Lax'로 설정하거나 Secure 속성을 false로 설정하는 것이 일반적인 조치로, 현재 우리 ganoverflow의 환경변수 분기에 따라 이를 적용하도록 수정하여 문제를 해결했다.

  async setCookieWithRefreshToken(res: any, refresh_token: string) {
    const cookieSecure = this.configService.get("COOKIE_SECURE") === "true"; // env파일 별 분기 string -> boolean 변환이요!
    const cookieDomain = this.configService.get("COOKIE_DOMAIN");
    const sameSitePolicy = cookieSecure ? "none" : "lax"; // Secure종속적 Samesite 정책!

    res.cookie("refresh_token", refresh_token, {
      httpOnly: cookieSecure,
      secure: cookieSecure,
      domain: cookieDomain,
      sameSite: sameSitePolicy,
      maxAge: 1000 * 60 * 60 * 24 * 7,
    });

    return res;
  }
profile
가용한 시간은 한정적이고, 배울건 넘쳐난다.

0개의 댓글