Skip to content

cross‐domain 로컬 환경에서 cookie로 인증 처리하기 with vite proxy ‐ 2024.11.20

Dongwoo Ko edited this page Nov 20, 2024 · 2 revisions

문제 상황

우리 서비스는 카카오 oAuth로그인을 활용해 인증을 처리한다.
oAuth로그인이 성공하면 http only 쿠키를 받아온다. (accessToekn, refreshToken, isReftesh)
여기서 쿠키의 도메인은 서버 주소다! ( 예를 들어 111.111.111.11)
배포환경일 때는 Domain이 같아서 잘 쿠키들이 담기겠지만 로컬에서 테스트할 때는 localhost111.111.111.11 라서 쿠키들이 담기지 않는다.
httpOnly 옵션을 적용해서 직접 자바스크립트로 쿠키를 꺼내서 담아줄 수도 없다..

가장 간편한 방법은 쿠키에 sameSite옵션에 None으로 설정하는 건데
현재 알파 서버가 https가 아닌 http라서 안 된다.
sameSite None은 https에서만 동작한다..!

왜 HTTP에서 SameSite=None이 동작하지 않을까? (gpt 답변)

  • SameSite=None은 쿠키를 크로스 사이트 요청에서 사용하도록 허용
  • 하지만 크로스 사이트 요청은 보안 위험(예: CSRF, 세션 하이재킹)을 동반할 수 있으므로, 이를 사용할 때 반드시 Secure 속성이 필요
  • Secure 속성은 HTTPS를 요구하므로, 결과적으로 HTTP 환경에서는 SameSite=None 쿠키를 사용할 수 없음.

해결 방법

또 다른 방법을 찾아본 결과 vite proxy 서버를 이용해 해결할 수 있었다!

전체적인 해결 흐름은 다음과 같다.

  1. vite proxy server 설정

  2. 서버로부터 개발용 임시 토큰 발급

  3. 응답 받은 토큰을 직접 js로 쿠키 설정

    쿠키키 domain이 localhost로 설정됨!

  4. api 요청 (웹브라우저 → vite proxy server)

    모두 도메인이 localhost라서 cookie 전송 잘 됨

  5. vite proxy server → 백엔드 서버 쿠키 전송

    서버 간 통신이므로 쿠키가 전송 잘 됨

image (7)

  1. vite proxy server 설정

    import { defineConfig, loadEnv } from 'vite';
    import react from '@vitejs/plugin-react';
    import tsconfigPaths from 'vite-tsconfig-paths';
    
    // https://vite.dev/config/
    export default defineConfig(({ mode }) => {
      const env = loadEnv(mode, process.cwd());
    
      return {
        plugins: [react(), tsconfigPaths()],
        server: {
          host: true,
          open: true,
          proxy: {
            '/api': {
              target: env.VITE_SERVER_URL,
              changeOrigin: true,
              secure: false,
            },
          },
        },
      };
    });

    target url을 env로 감싸기 위해 loadEnv(mode, process.cwd()); 로 env 정보 가져와서 적용했다!

    ++defineConfig 내에서 import.meta.env를 직접 사용할 수 없는 이유? (gpt 답변)

    • import.meta.env는 브라우저나 빌드 프로세스에서 런타임에 사용됨
    • 반면, Vite의 설정 파일(vite.config.ts/js)은 Node.js 환경에서 실행되며, 이 시점에는 import.meta.env가 정의되지 않는다.
  2. 서버에 개발용 임시 토큰 발급

      const handleKakaoBtnClick = async () => {
        if (import.meta.env.DEV) {
          **const res = await login('jindding', '1234');**
    
          // ...
          return;
        }
    
        window.location.href = `${import.meta.env.VITE_API_URL}/auth/kakao`;
      };

    accessToken을 response body에서 가져올 수 있다!

  3. 받아온 accessToken을 자바스크립트로 직접 설정

      const handleKakaoBtnClick = async () => {
        if (import.meta.env.DEV) {
          const res = await login('jindding', '1234');
    
          if ('error' in res) {
            setErrorCode(res.statusCode);
            return;
          }
    
          **document.cookie = `accessToken=${res.accessToken}; path=/;`;**
          return;
        }
    
        window.location.href = `${import.meta.env.VITE_API_URL}/auth/kakao`;
      };

    document.cookie로 웹브라우저 쿠키저장소에 accessToken을 담는다.

    이 때 cookie Domain은 localhost가 된다!

    image (12)
  4. 쿠키로 인증이 필요한 api 요청

    웹브라우저, vite proxy server 모두 domain이 localhost라서 cookie가 잘 전달된다.

    image (10) image (11)

    requestHeader Cookie에 accessToken이 잘 담기는 것을 확인할 수 있다!

  5. vite proxy server → 백엔드 서버

    export default defineConfig(({ mode }) => {
      const env = loadEnv(mode, process.cwd());
    
      return {
        plugins: [react(), tsconfigPaths()],
        server: {
          host: true,
          open: true,
          proxy: {
            '/api': {
              target: env.VITE_SERVER_URL,
              changeOrigin: true,
              secure: false,
            },
          },
        },
      };

    vite.config.ts에 설정해주었던대로 vite proxy server는 taget으로 지정한 VITE_SERVER_URL로 요청하게 된다! 서버와 서버 간에 통신이므로 쿠키를 포함해서 보내게 된다.

++proxy 서버를 안두고 개발용 임시 토큰만 받는다면??

image (8)

localhost ≠ 111.111.111.11 same site가 아니기 때문에 쿠키 전송 x

++ 서버에 개발용 임시 토큰을 발급하지 않는다면??

image (9)

서버에 개발용 임시 토큰을 발급하지 않으면 쿠키 통신을 할 수 없다.

Why?

지금은 cookie의 domain이 서버(111.111.111.11)다.

브라우저, vite proxy server 모두 localhost로 같은 도메인이지만 cookie 도메인이 다르기 때문에 전달되지 않는다!

→ 쿠키 도메인이 무조건 localhost여야 한다!

Ref

https://yozm.wishket.com/magazine/detail/2565/
https://0422.tistory.com/329

📜 개발 일지

⚠️ 트러블 슈팅

❗ 규칙

🗒️ 기록

기획
회의록
데일리스크럼
그룹 멘토링
그룹 회고

😲 개별 멘토링

고동우
김진
서산
이시은
박진명
Clone this wiki locally