withCredentials 설정을 위한 탐구

seul_velog·2023년 4월 14일
post-thumbnail

withCredentials

fetchData.ts 함수를 정의하면서 fetch api로 작업을 하던 도중 withCredentials 옵션에 대해 알게 되었다. 이 옵션은 초기값이 무엇이고 왜 사용하는 걸까? 🤔
그리고 withCredentials을 알아가면서 보이는 여러 통신관련 키워드에 대해서도 다시한번 체크해보자 😤

웹 브라우저의 XMLHttpRequests 또는 Fetch API에서 사용되는 옵션으로써 크로스 도메인 요청 시 쿠키, HTTP 인증 및 클라이언트 SSL 인증서를 사용하도록 허용한다.

  • 기본값은 false 이다.
  • withCredentials는 크로스 도메인 요청에서 인증 정보와 쿠키를 포함시키기 위한 클라이언트 측 옵션이다.
  • 이 옵션만으로는 충분하지 않으며, 서버 측 설정도 함께 고려해야 한다.

XMLHttpRequest:

웹 브라우저의 기본 API이다. 웹 애플리케이션에서 서버로 비동기적으로 데이터를 전송하기 위해 사용되는 오래된 방법이다.

var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/data', true);
xhr.onload = function() {
  if (xhr.status >= 200 && xhr.status < 400) {
    var data = JSON.parse(xhr.responseText);
    console.log(data);
  }
};
xhr.send();



Fetch()

fetch()는 최신의 웹 API중 하나로, 비동기적인 HTTP 요청을 보내기 위한 방법이다. Promise 기반으로 동작하며 사용하기 더 직관적이고 간결하다.
✍️ fetch api 정리 보러가기

fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));



axios

axios는 외부 라이브러리로, HTTP 요청을 보내기 위해 자주 사용되는 도구중 하나이다. Promise 기반이며, 요청 취소, 요청 및 응답을 중간에 변환하거나, 전역적인 요청/응답 설정 등과 같은 다양한 추가 기능을 제공한다.

axios.get('https://api.example.com/data')
  .then(response => console.log(response.data))
  .catch(error => console.error('Error:', error));



withCredentials 옵션을 사용하는 상황

AJAX요청을 보낼 때(axios나 fetch를 사용해서) withCredentials 옵션을 사용할 수 있다. 주로 백엔드 서버와의 인증 또는 세션 관리를 위해 필요하다.

axios.get('https://example.com/api/data', {
  withCredentials: true
});

(1) 크로스 도메인 쿠키 전송

도메인A에서 도메인B로 AJAX요청을 보낼 때 'withCredentials'를 ture로 설정하면 도메인A에 저장된 쿠키를 도메인B로 전송한다.

❓ 왜 서로 다른 도메인끼리 AJAX요청시 타 도메인의 쿠키가 필요한걸까? 사실 이 부분이 제일 궁금해서 알아보기 시작한 글이었다. 🧐

👉 위와 같이 설정하면 도메인 B서버는 도메인 A에서 보낸 요청에 포함된 쿠키를 읽을 수 있게된다. 따라서 도메인 B의 서버가 도메인 A의 사용자를 인식할 수 있게 하는 것이다.
예를들면, 사용자가 도메인 A에서 로그인을 하고, 그 후에 도메인 A에서 도메인B로 AJAX요청을 보낼 때, 도메인 B는 사용자가 도메인 A에서 로그인한 상태임을 알 수 있게 되는 것이다.

❓ 그렇다면 왜 도메인B에서는 도메인A의 상태를 알아야 할까?

👉 도메인 간 쿠키 공유와 관련된 특정 케이스

  • 서브 도메인 간 인증 : 대규모 웹사이트에서 'example.com' 및 'shop.example.com' 과 같은 여러 서브 도메인이 존재할 수 있다. 사용자가 'example.com'에서 로그인한 뒤 'shop.example.com' 에서도 로그인 상태를 유지하려면 쿠키가 서브 도메인 간에 공유되어야 하기 때문이다.

  • 다른 도메인과의 통합 : 예를들어, 소셜 미디어 로그인 기능이 있는 웹사이트에서 사용자가 'siteA.com'에서 로그인하고, 'siteB.com'에서 해당 사용자의 정보를 가져와서 특정 기능을 제공하려는 경우이다. 이 경우 'siteA.com'에서 로그인 시 생성된 쿠키를 'siteB.com'으로 전송할 수 있다.

  • 광고 및 추적 : 여러 도메인에서 사용자 활동을 추적하기위해 광고 네트워크는 쿠키를 여러 사이트 간에 공유할 수 있다.


(2) HTTP인증

Basic 인증 같은 HTTP 인증 방법을 사용하여 요청을 보낼 때 인증 정보를 전송하려면 이 옵션이 필요하다.

  • HTTP 인증은 웹에서 리소스에 접근하려면 클라이언트가 자신을 식별해야 한다는 원칙을 기반으로 한다.
  • 웹 브라우저나 다른 클라이언트가 웹 서버에 요청을 보낼 때, 서버는 해당 요청을 인증할 수 있다. 인증에 실패하면 401 Unauthorized 응답을 반환한다.

Basic 인증

: HTTP의 가장 기본적인 인증 방법 중 하나이다. 사용자의 아이디와 비밀번호를 : 로 구분하여 합친 다음, 이 문자열을 Base64로 인코딩한다. 인코딩된 문자열은 HTTP 요청 헤더의 Authorization 필드에 추가된다.
(예: Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==)

Base64는 쉽게 디코딩할 수 있다. 단순 base64 인코딩된 사용자 ID와 비밀번호를 HTTP로 전달하면 요청의 보안이 보장되지 않는다. 따라서 보안적으로 안전하지 않은 Basic인증 방식을 사용할 때는 HTTPS와 같은 보안 프로토콜을 함께 사용하여 통신해야 안전하다고 하다.

❓보안적으로 안전하지 않다? 🤔
👉 Basic 인증에서 사용되는 Base64 인코딩은 데이터를 변환하는 방식일 뿐, 실제로 데이터의 내용을 보호하기 위한 보안 수단은 아니다.

Base64 인코딩의 목적은 바이너리 데이터를 ASCII 문자열 형태로 변환하여 텍스트 기반의 시스템에서 안전하게 전송하고 저장할 수 있도록 하는 것이다. Base64 인코딩은 원본 데이터를 손실 없이 변환하므로, Base64로 인코딩된 문자열은 원래의 데이터로 쉽게 디코딩할 수 있다.

따라서 Basic 인증에서 "아이디:비밀번호" 문자열을 Base64로 인코딩하면, 그 결과는 실제 아이디와 비밀번호를 숨기기 위한 것이 아니라, HTTP 헤더에서 안전하게 전송할 수 있는 형태로 만들기 위한 것이다.

즉, Base64 인코딩된 Authorization 헤더를 가진 HTTP 요청을 가로채면, 그 헤더를 쉽게 디코딩하여 원본 "아이디:비밀번호" 문자열을 얻을 수 있다. 이것이 Basic 인증의 주요 취약점 중 하나이며, 이러한 이유로 Basic 인증을 사용할 때는 HTTPS와 같은 보안 프로토콜을 함께 사용하는 것이 매우 중요하다고 한다. 😀


(3) 클라이언트 SSL 인증서

웹 페이지가 클라이언트 SSL인증서를 요구하는 경우, 이 옵션을 사용하여 요청에 인증서를 포함시킬 수 있다.

SSL 인증서

  • 일반적으로 서버 인증서라고도 한다.
  • 웹 서버의 신원을 증명하고, 서버와 클라이언트 간의 암호화된 연결을 설정하는 데 사용된다.
  • 대부분의 웹사이트에서 HTTPS를 사용할 때, 이 인증서는 웹 브라우저에게 해당 웹사이트가 신뢰할 수 있는지 확인하는 데 사용된다. 웹 브라우저는 인증서에 포함된 정보와 신뢰할 수 있는 인증 기관(CA)목록을 비교하여 웹사이트의 신뢰성을 평가한다.

클라이언트 SSL 인증서

  • 웹 브라우저나 다른 클라이언트의 신원을 웹 서버에 증명하는 데 사용된다.
  • 서버 인증서와 비슷한 방식으로 작동하지만, 목적이 반대이다. 서버인증서는 서버의 신원을 클라이언트에 증명하고, 클라이언트 인증서는 클라이언트의 신원을 서버에 증명한다.

왜 웹페이지는 클라이언트 SSL 인증서를 요구할까

  • 클라이언트 SSL 인증서는 특정 웹 페이지나 애플리케이션에 접근하는 사용자의 신원을 보다 엄격하게 검증하는 데 사용된다.
  • 예를 들면, 기업 내부의 중요한 시스템, 금융 관련 웹사이트, 정부 기관 웹사이트 등에서 추가적인 보안 수준이 필요할 때 이런 방식을 사용할 수 있다.
  • 사용자 이름과 비밀번호만으로는 충분하지 않은 경우, 클라이언트 인증서를 통해 두번째 인증 수단으로 사용될 수 있다.

클라이언트 SSL 인증서를 사용할 때, 웹 브라우저는 해당 인증서와 관련된 개인 키를 사용하여 웹 서버에 자신의 신원을 증명한다. 이 과정은 웹 브라우저와 웹 서버 간의 TLS 핸드쉐이크 도중에 자동으로 이루어진다고 한다. 🤔



withCredentials 사용하려면

  • 서버 측에서도 적절한 CORS(Cross-Origin Resource Sharing)헤더 설정이 필요하다.

    즉, 도메인 A에서 withCrendentialstrue 로 설정 후 요청하더라도, 도메인 B의 서버에서는 해당 요청을 올바르게 처리하기 위해 추가 설정이 필요하다. 특히 CORS 설정에서 Access-Control-Allow-Credentials 헤더를 true로 설정하거나, Access-Control-Allow-Origin 헤더는 와일드카드(*) 대신 명시적인 도메인(https://sitename.com) 을 포함해야 한다고한다. 🧐

    이렇게 설정을 하지 않는다면 브라우저는 보안 정책 때문에 크로스 도메인 요청을 차단할 것이다.




HTTPS / SSL / TLS

SSL(Secure Sockets Layer)

  • 웹 서버와 웹 브라우저 간의 통신을 암호화하는 프로토콜이다.
  • SSL은 1990년대에 Netscape에 의해 처음 개발되었다.
  • 시간이 지나면서 SSL의 여러 버전이 나왔고, 보안 취약점들이 발견되었다.

TLS(Transport Layer Security)

  • SSL의 후속 버전으로, 보안 강화와 몇 가지 기능 추가를 위해 설계되었다.
  • TLS는 현재 웹 보안에서 권장되는 표준 프로토콜이다.
  • 일반적으로 사람들은 SSL 이라는 용어를 사용하지만, 현대 보안된 연결은 대부분 TLS를 기반으로 한다.

HTTPS(Hyper Text Transfer Protocol Secure)

  • HTTP 프로토콜의 보안된 버전이다.
  • 웹 서버와 클라이언트 간의 통신을 암호화하기 위해 SSL 또는 TLS를 사용한다.
  • 웹 브라우저 주소창에 "https://" 로 시작하는 URL은 해당 사이트가 HTTPS를 사용하여 통신을 암호화 하고 있음을 나타낸다.

✍️ 따라서, SSL과 TLS는 웹 통신을 보안하기 위한 프로토콜들이며, HTTPS는 이러한 프로토콜들을 사용하여 웹 트래픽을 암호화하는 방법이다. 현재는 SSL보다는 TLS가 더 안전하고 현대적인 프로토콜로 간주되며, 대부분의 웹 사이트는 TLS를 사용하여 HTTPS 연결을 제공한다.

+) 웹 트래픽은 웹 서버와 클라이언트 간에 교환되는 데이터를 의미하며, HTTPS와 같은 보안 프로토콜을 사용하면 이러한 웹 트래픽이 암호화되어 외부의 눈에는 보이지 않게 된다.




정리 ✍️

HTTP? 프로토콜? 웹트래픽? Basic 인증? Base64? HTTPS? 인코딩? 암호화? 보안? 크로스 도메인? 많은 개념들의 나열로 헷갈릴 수도 있을 것 같다고 생각했다. 정리를 해보자!

1. HTTP 인증 (예: Basic 인증)

  • HTTP 인증은 클라이언트가 서버에 대한 자신의 신원을 증명하는 방법
  • Basic 인증의 경우, 사용자 이름과 비밀번호가 HTTP 헤더에 포함되어 전송
  • Basic 인증 자체는 아이디와 비밀번호를 "암호화"하지 않음. 대신 Base64 인코딩을 사용하여 "텍스트 기반 시스템에서 안전하게 전송"될 수 있도록 함. 이는 "보안"을 제공하는 것이 아닌 "전송 형식"을 조정하는 것

2. HTTPS:

  • HTTPS는 웹 트래픽 전체를 암호화하는 방법
  • 이는 SSL 또는 TLS 프로토콜을 사용하여 구현
  • HTTPS는 특정 인증 방법 (예: Basic 인증)에 상관없이 모든 웹 트래픽을 암호화
  • 따라서, 중요한 정보 (예: 로그인 정보)를 전송할 때는 항상 HTTPS를 사용하여 전체 통신을 암호화해야함. 그렇지 않으면 중간에 데이터를 가로채는 공격자가 인코딩된 정보를 쉽게 디코딩하여 원본 아이디와 비밀번호를 알아낼 수 있음.

3. withCredentials 옵션에 대해

  • 크로스 도메인 요청에서 쿠키나 Basic 인증 정보와 같은 자격 증명을 함께 보내려면 withCredentials를 true로 설정해야 함.
  • HTTPS 사용 여부와는 별도로 고려되어야 함. 즉, HTTPS를 사용하더라도 크로스 도메인 상황에서 자격 증명을 전송하려면 withCredentials가 true로 설정되어야 함.

요약하면, HTTP 인증 (예: Basic 인증)은 클라이언트가 서버에 자신을 식별하는 방법이다. 그러나 이 정보를 안전하게 전송하려면 HTTPS를 사용해야 한다.
그리고 크로스 도메인 요청에서 자격 증명을 함께 보내려면 withCredentials를 true로 설정해야 한다. 😀

✍️
크로스 도메인 요청상황이 아니라면 이 옵션의 중요성은 크게 감소할 것이다. 하지만 만일 크로스 도메인 요청이 필요한 상황이라고 가정해보자.
크로스 도메인 요청 자체는 보안적으로 고려해야 할 것들이 많은 상황이 생길 수 있을 것이다.
따라서 withCredentials 옵션을 true로 설정하여 이를 통해 SSL인증서를 요청에 포함시키거나, HTTP인증 정보를 전송하거나 함으로써 보안적으로 증명된 요청을 할 수 있을 것이고, 필요하다면 크로스 도메인 쿠키를 전송할 때에도 필요할 것이다.




📌 이때 계속해서 보이는 단어가 있다. 그리고 크로스 도메인... 계속 떠오르는 개념이있다. 그것은 바로! 👇

CORS(Cross-Origin Resource Sharing)

웹 페이지가 다른 도메인의 리소스에 접근할 수 있도록 브라우저에헤 허용하는 보안 메커니즘이다. CORS는 웹 페이지의 보안 모델인 "동일 출처 정책(Same-Origin Policy)"의 제한을 완화하는 데 사용된다.

동일 출처 정책(Same-Origin Policy)

  • 웹 브라우저는 보안상의 이유로 스크립트 내에서 다른 출처의 리소스에 직접 접근하는 것을 제한한다.
  • 예를들어 'domainA.com'에서 실행되는 JavaScript는 기본적으로 'domainB.com'의 데이터에 접근할 수 없다.

CORS의 필요성

  • 현대 웹 애플리케이션에서는 다양한 웹 서비스와 상호작용하는 경우가 많다. 예를들어, 메인 웹 페이지와 API 서버가 다른 도메인에서 호스팅 되는 경우, API 호출 시 동일 출처 정책에 의해 제한될 수 있다.
  • 이러한 제한을 해결하기 위해 CORS가 도입되었다.

CORS 동작 방식

  • 웹 페이지에서 다른 출처의 리소스에 접근하려고 시도하면, 브라우저는 해당 요청에 'Origin' 헤더를 포함시킨다. 이 헤더는 요청을 보내는 페이지의 출처를 나타낸다.
  • 서버는 응답에 'Access-Control-Allow-Origin' 헤더를 포함하여 해당 출처의 접근을 허용할지를 결정한다. 서버가 특정 출처의 접근을 허용한다면, 그 출처는 응답된 리소스에 접근할 수 있다.
  • 추가적으로, 'withCredentials' 옵션을 사용하여 자격증명을 포함한 요청을 보낼 경우, 서버는 'Access-Control-Allow-Credentials' 헤더도 'true'로 설정해야 한다.

CORS를 설정하지 않는다면

  • CORS 설정을 하지 않고 다른 출처의 리소스에 접근하려고 시도하면, 브라우저는 보안 위반으로 간주하고 해당 요청을 차단한다.
  • 이 때, 웹 콘솔에는 CORS 관련 오류 메시지가 표시된다.

서버에서의 CORS 설정

  • 서버에서는 요청을 처리하는 로직에 따라 CORS 헤더를 설정해야 한다.
  • 예를 들어, Express.js를 사용하는 Node.js 서버에서는 'cors' 미들웨어를 사용하여 CORS 설정을 쉽게 할 수 있다고 한다. 🤔

✍️ 웹 페이지는 보안 때문에 다른 웹사이트의 데이터에 직접 접근할 수 없다. 이 규칙을 '동일 출처 정책' 이라고 한다. 그런데 떄로는 다른 웹사이트의 정보나 기능을 사용해야 할 때가 있을 것이다. CORS는 이런 상황에서 브라우저에게 '이번만 허용해 줘' 라고 말하는 방법이라고 정리를 하겠다.




profile
기억보단 기록을 ✨

0개의 댓글