# CORS

## Origin

<figure><img src="https://1965920705-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGyWfehQpIoHLe9fbqJ4Q%2Fuploads%2FJenIvJE3IuouMtLLg0Lm%2Fimage.png?alt=media&#x26;token=89531f87-7b54-4a8f-896a-9ac4f167265c" alt=""><figcaption><p>URL구성요소</p></figcaption></figure>

URI에서 Protocol, Host, Port부분을 origin이라 부른다.

{% content-ref url="url-vs-uri-vs-urn" %}
[url-vs-uri-vs-urn](https://gaepodong.gitbook.io/about-web/network/url-vs-uri-vs-urn)
{% endcontent-ref %}

그리고 해당 origin이 같은 경우 SOP에 부합하기에 CORS가 허용된다.

## SOP & CORS

> SOP(Same Origin Policy), CORS(Cross Origin Resource Sharing)

앞서 말했듯이 SOP는 다른 Origin으로 요청을 보낼 수 없도록 금지하는 브라우저의 기본 보안 정책이다. 예전에는, 다른 Origin으로 보내는 것이 엄격하게 금지되었지만, 몇가지 예외 사항이 있다.

1. `<script>` 태그를 활용하는 경우
2. 이미지 렌더링을 하는 경우
3. `<link>` 태그를 사용하는 경우
4. HTML 문서를 화면에 띄우는 경우
5. CORS 정책을 지키는 요청을 하는 경우

즉 CORS는 다른 Origin으로 요청을 보내기 위한 정책 + SOP를 풀어주는 정책 이라 할 수 있다.

{% hint style="info" %}
CORS 는 브라우저 정책임에 주의
{% endhint %}

> 기본적인 CSRF 공격을 방어해준다

## CORS flow

> 다른 Origin으로 요청 보낼 시 Origin 헤더에 자신의 Origin을 설정하여, 서버로부터 응답을 할 때 `Access-Control-Allow-Origin`헤더의 목록에 포함되어 있는지 검사

### Simple Request

> 안전한 요청으로 취급이 되며, Preflight 없는 한 번의 요청으로 전송이 되는 경우

<figure><img src="https://1965920705-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGyWfehQpIoHLe9fbqJ4Q%2Fuploads%2FRc41zj5ROSxvoxLB4VHq%2Fimage.png?alt=media&#x26;token=c8154a96-e0db-482d-b535-06dc8c91759d" alt=""><figcaption><p>Simple Request</p></figcaption></figure>

하지만 Simple Request를 만족시키는 조건이 꽤나 까다롭다

* Method가 GET, HEAD, POST 중 하나
* 아래와 같은 헤더만 사용
  * Accept
  * Accept-Language
  * Content-Language
  * Content-Type
    * application/x-www-form-urlencode
    * multipart/form-data
    * text/plain
  * DPR
  * Downlink
  * Save-Data
  * Viewport-Width
  * Width<br>

### Preflight Request

앞에 언급한 Simple Request가 아닌 경우, 안전한 요청인지 확인하는 Preflight 과정이 필요하게 된다.

<figure><img src="https://1965920705-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGyWfehQpIoHLe9fbqJ4Q%2Fuploads%2FVW2vFXoaBN67rYb9lac1%2Fimage.png?alt=media&#x26;token=f210d825-d6d1-4a90-9397-dbae857129ba" alt=""><figcaption><p>Preflight Request Flow</p></figcaption></figure>

Preflight Request의 특징은 다음과 같다

* Method로 OPTIONS 사용
* Origin헤더에 자신의 Origin 설정
* Access-Control-Request-Method 헤더에 실제 사용할 메소드 설정
* Access-Control-Request-Headers에 실제 사용할 헤더 설정

Preflight Respond는 다음과 같다

* Access-Control-Allow-Origin 헤더에 허용되는 Origin의 목록 및 `*`을 설정
* Access-Control-Allow-Methods 헤더에 허용되는 메소드 혹은 `*` 을 설정
* Access-Control-Allow-Headers 헤더에 허용되는 목록 혹은 `*` 을 설정
* Access-Control-Max-Age 헤더에 해당 Preflight요청이 캐시될 수 있는 최대 시간을 설정

해당 응답을 받으면 브라우저는 자신이 전송한 요청과 비교하여 안전성을 검사할 수 있다.

### Credential Request

일반적으로 Cookie 혹은 Authorization 헤더에 존재하는 토큰은 별도로 지정해주지 않는한 전송하지 않는다. 그래서 별도로 CORS 정책을 설정해주어야 된다.

XMLHttpRequest, ajax, axios 등은 `withCredentials` 옵션을 `true` 로 설정해주면 되고, `fetch` 인 경우 `credentials` 옵션을 `include` 로 설정해주어야 된다.

{% hint style="info" %}
Access-Control-Allow-Origin 헤더가 `*` 가 아닌, 분명한 Origin으로 설정되고, 서버의 Access-Control-Allow-Credentials 헤더가 `true` 로 설정되어야 함에 주의
{% endhint %}

<figure><img src="https://1965920705-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGyWfehQpIoHLe9fbqJ4Q%2Fuploads%2F3VWYW6VIbdVaCROqfBby%2Fimage.png?alt=media&#x26;token=ddf420c5-deca-49fe-b019-577c16d53e61" alt=""><figcaption><p>Credential Request flow</p></figcaption></figure>

참고

{% embed url="<https://it-eldorado.tistory.com/163>" %}
