【AWS SAP】CORSとは

# CORSとは
## CORSがいらない世界

```mermaid
graph TD
    User[ブラウザ] -->|リクエスト| Server[ウェブサーバー]
    Server -->|データベースから取得| Database[データベース]
    Server -->|レスポンス| User
```
## CORSがいる世界

```mermaid
graph TD
    User[ブラウザ] -->|リクエスト| Frontend[フロントエンドサーバー]
    Frontend -->|APIリクエスト| Backend[バックエンドAPIサーバー※**CORS設定**]
    Backend -->|データベースから取得| Database[データベース]
    Backend -->|レスポンス| Frontend
    Frontend -->|データを返す| User
```

### 説明
1. ユーザーがフロントエンドサーバー（例：ウェブアプリ）にリクエストを送ります。
2. ウェブアプリケーションが動作しているサーバーで、バックエンドAPIサーバーにリクエストを送信します。
3. フロントエンドからのリクエストを処理し、データベースから必要な情報を取得します。
4. バックエンドAPIサーバーがフロントエンドにデータを返し、最終的にブラウザに表示します。

### CORSが必要な理由
フロントエンドサーバーがバックエンドAPIサーバーにリクエストを送る際、異なるオリジン間の通信となるため、CORSを設定してリクエストを許可する必要があります。

つまり、**バックエンドAPIサーバーがどのオリジンからのリクエストを許可する**を明確にCORS設定が必要です。

### オリジンサーバがS3の場合
S3バケットにCORS設定を行います。最低限の設定は以下の通りです。
```:s3バケットCORS設定例
[
    {
        "AllowedOrigins": ["https://example.com"],
        "AllowedMethods": ["GET", "POST"],
        "AllowedHeaders": ["Content-Type", "Authorization"]
    }
]
```
※画像の取得（GET）とアップロード（POST）を許可する最小限のCORS設定

## 改めてCORSとは
**CORS (Cross-Origin Resource Sharing)** は、ブラウザで動作するウェブアプリケーションが、異なるオリジン（プロトコル、ドメイン、ポートの組み合わせ）間で安全にリソースを共有するための仕組みです。

ウェブブラウザには、**同一オリジンポリシー (Same-Origin Policy)** というセキュリティ制限があり、異なるオリジン間での通信をデフォルトでブロックします。この制限により、不正なスクリプトや情報漏洩のリスクを軽減していますが、ウェブアプリケーションの一部では、異なるオリジン間の通信が必要になることがあります。この課題を解決するのがCORSです。

## 同一オリジンポリシーとは

**同一オリジンポリシー**は、以下の条件がすべて一致する場合にのみ、リソースへのアクセスを許可するセキュリティモデルです：

- **プロトコル**: 例) `http` と `https` は異なるプロトコル  
- **ドメイン名**: 例) `example.com` と `api.example.com` は異なる  
- **ポート番号**: 例) `https://example.com:80` と `https://example.com:443` は異なる  

この制約により、外部サイトがユーザーのデータやセッション情報にアクセスすることを防ぎます。

## CORSが必要になるケース

現代のウェブ開発では、以下のような状況で異なるオリジン間の通信が発生します：

1. **フロントエンドとバックエンドが別のオリジンに配置されている場合**  
   - 例：  
     - フロントエンド：`https://frontend.com`  
     - バックエンド：`https://api.backend.com`
　
2. **CDNやクラウドサービスを利用している場合**  
   - 例：静的リソースをCDN（例: CloudFront）から配信し、APIリクエストは別のオリジンに送る。
　
3. **外部APIを利用する場合**  
   - 例：Google Maps APIや他社のREST APIを利用。

ブラウザがこのようなリクエストをブロックしてしまうため、サーバー側でCORSを適切に設定することで、通信を許可します。

### フロー図：CORS設定が必要なケース
```mermaid
flowchart TD
    A[ウェブブラウザ] -->|リクエスト| B[サーバー]
    B -->|異なるオリジン| C[同一オリジンポリシー適用]
    C -->|リクエスト拒否| D[エラー発生]
    C -->|CORS設定確認| E[CORSヘッダーなし]
    E -->|リクエスト拒否| D
    C -->|CORSヘッダーあり| F[リクエスト許可]
```

## CORSの基本的な考え方

CORSは、**サーバーが許可するオリジンを明示的に指定**し、ブラウザにその情報を伝える仕組みです。具体的には、以下の手順で動作します：

1. **ブラウザがリクエストを送信**  
   - リクエストには発信元オリジン情報（例：`Origin: https://frontend.com`）が含まれます。
　
2. **サーバーが応答**  
   - サーバーは、`Access-Control-Allow-Origin` ヘッダーをレスポンスに含めることで、特定のオリジンからのアクセスを許可します。
　
3. **ブラウザが許可を確認**  
   - ブラウザはサーバーのレスポンスヘッダーをチェックし、通信を許可するかどうかを判断します。

例として、以下のようなやり取りが行われます。

- リクエストヘッダー：
  ```
  Origin: https://frontend.com
  ```
- サーバーのレスポンスヘッダー：
  ```
  Access-Control-Allow-Origin: https://frontend.com
  ```
ブラウザは、このレスポンスを確認して、リクエストを許可するかどうかを判断します。

### フロー図：CORS設定有効化後の通信フロー
```mermaid
flowchart TD
    A[ウェブブラウザ] -->|リクエスト| B[サーバー]
    B -->|異なるオリジン| C[CORS設定確認]
    C -->|CORSヘッダーあり| D[リクエスト許可]
    C -->|CORSヘッダーなし| E[リクエスト拒否]
    D -->|正常な応答| F[リソース取得成功]
```

## プリフライトリクエストとは

CORSでは、特定の条件を満たすリクエストの場合、ブラウザが事前に「このリクエストを送信してもよいか」を確認するために**プリフライトリクエスト (Preflight Request)** を送信します。これは、`OPTIONS` メソッドを使ったリクエストで、以下を確認します：

- 許可されるHTTPメソッド（例：`GET`, `POST`, `PUT`）  
- 許可されるカスタムヘッダー（例：`Authorization`, `Content-Type`）  

### プリフライトリクエストの例

- リクエストヘッダー（OPTIONSメソッド）：
  ```
  Access-Control-Request-Method: POST
  Access-Control-Request-Headers: Authorization
  Origin: https://frontend.com
  ```

- サーバーのレスポンスヘッダー：
  ```
  Access-Control-Allow-Origin: https://frontend.com
  Access-Control-Allow-Methods: POST
  Access-Control-Allow-Headers: Authorization
  ```

プリフライトリクエストが成功した場合のみ、ブラウザは本来のリクエスト（`POST` リクエスト）を送信します。

## まとめ

CORSは、単純なリクエストから複雑なリクエストまで柔軟に対応することで、異なるオリジン間の通信を安全かつ効果的に行えるようにする仕組みです。この仕組みを理解することで、ウェブアプリケーションのセキュリティと機能性を向上させることができます。