【Go Echo】CSRF対策 + JWT認証

# はじめに

前回の記事では、[Golang EchoフレームワークでJWT認証を実装する方法
](https://qiita.com/syukan3/items/d8f0d900a0926604f090)について解説しました。

今回は、このアプリケーションに**CSRF（Cross-Site Request Forgery）対策**を追加し、セキュリティをさらに強化する方法を紹介します。

## CSRFとは？

**CSRF（クロスサイトリクエストフォージェリ）** は、ユーザーが意図しないリクエストを第三者が送信させる攻撃手法です。

これを防ぐために、**CSRFトークン** を用いてリクエストの正当性を検証します。

## 追加する機能の概要

1. **CSRFミドルウェアの設定**
2. **CSRFトークン取得用エンドポイントの追加**
3. **クライアント側でのトークン送信**

## 1. CSRFミドルウェアの設定

EchoにはCSRF対策用のミドルウェアが用意されています。`server.go`に以下の設定を追加します。

```go
import (
    // 既存のインポートに加えて
    "github.com/labstack/echo/v4/middleware"
)

func main() {
    // 既存のコード...

    // CSRFミドルウェアの設定
    csrfConfig := middleware.CSRFConfig{
        TokenLookup: "header:X-CSRF-Token", // ヘッダーからトークンを取得
        CookieName:  "csrf_token",          // クッキー名
        Secure:      false,                 // HTTPS使用時はtrue
    }
    e.Use(middleware.CSRFWithConfig(csrfConfig))

    // 既存のルート設定...
}
```

## 2. CSRFトークン取得用エンドポイントの追加

クライアントがCSRFトークンを取得できるように、エンドポイントを追加します。

```go
// CSRFトークンを取得するハンドラー
func getCSRFToken(c echo.Context) error {
    csrfToken := c.Get(middleware.DefaultCSRFConfig.ContextKey).(string)
    return c.JSON(http.StatusOK, echo.Map{
        "csrf_token": csrfToken,
    })
}

func main() {
    // 既存のコード...

    // CSRFトークン取得エンドポイント
    e.GET("/csrf", getCSRFToken)

    // 既存のルート設定...
}
```

## 3. クライアント側でのトークン送信

クライアントは、`/csrf`エンドポイントから取得したトークンを、後続のリクエストヘッダーに含めて送信します。

```javascript
// CSRFトークンの取得
async function getCSRFToken() {
    const response = await fetch('/csrf', {
        method: 'GET',
        credentials: 'include',
    });
    const data = await response.json();
    return data.csrf_token;
}

// トークンを含めたリクエスト
async function createUser(userData, jwtToken) {
    const csrfToken = await getCSRFToken();

    const response = await fetch('/users', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'X-CSRF-Token': csrfToken,
            'Authorization': `Bearer ${jwtToken}`,
        },
        body: JSON.stringify(userData),
    });

    return await response.json();
}
```

## 動作確認

1. **サーバーの起動**

    ```bash
    go run server.go
    ```

2. **CSRFトークンの取得**

    ```bash
    curl -X GET http://localhost:1323/csrf -c cookies.txt
    ```

3. **CSRFトークンを使用してログイン**

    ```bash
    curl -X POST http://localhost:1323/login \
    -H "Content-Type: application/json" \
    -H "X-CSRF-Token: YOUR_CSRF_TOKEN" \
    -b cookies.txt \
    -d '{"email":"user@example.com","password":"password"}'
    ```

4. **保護されたエンドポイントへのアクセス**

    ```bash
    curl -X POST http://localhost:1323/users \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer YOUR_JWT_TOKEN" \
    -H "X-CSRF-Token: YOUR_CSRF_TOKEN" \
    -b cookies.txt \
    -d '{"name":"Jane Doe","email":"jane@example.com","password":"securepassword"}'
    ```

**注意点**:
- `-c cookies.txt` はクッキーを保存します
- `-b cookies.txt` は保存したクッキーを送信します
- `YOUR_CSRF_TOKEN` は手順2で取得したトークンに置き換えてください
- `YOUR_JWT_TOKEN` は手順3で取得したJWTトークンに置き換えてください

正常にユーザーが作成されれば、CSRF対策とJWT認証の両方が正しく機能していることを確認できます。エラーが発生した場合は、トークンが正しく設定されているか確認してください。
## まとめ

今回、Go Echoを使用したJWT認証アプリケーションにCSRF対策を追加する方法を紹介しました。
EchoのCSRFミドルウェアを活用することで、簡単にセキュリティを強化できます。
セキュリティは継続的に見直すことが重要ですので、他の対策も併せて検討しましょう。

# 関連リンク

- [Echo公式ドキュメント - Middleware](https://echo.labstack.com/middleware)
- [OWASP CSRF対策](https://owasp.org/www-community/attacks/csrf)

---
### 会社紹介

**株式会社 Mosaica**  
最先端テクノロジーで社会課題を解決し、持続可能な未来を創造する IT カンパニー。
AI ソリューション、クラウド統合、DX 推進、経営コンサルティングなど包括的なサービスでビジネス変革を支援しています。  

詳しくは [公式サイト](https://mosaica.co.jp/) までお気軽にご相談ください。
公式サイト： https://mosaica.co.jp/