OAuth 2.0の基本とSlack連携の実践：安全な認証と認可の完全ガイド

:::note info
本記事の内容は、以下の公式ドキュメントを参考にしています。
:::
https://api.slack.com/distribution

# イントロ

**OAuth 2.0**は、ユーザーのログイン情報やパスワードを共有することなく、第三者アプリケーションがユーザーのデータや機能に安全にアクセスできるようにする認可フレームワークです。

### 特徴

- ユーザーが明示的にアプリケーションへの権限付与を行える
- 必要最小限の権限でアプリケーションの安全な動作を実現
- アクセス権の管理が容易で、セキュリティリスクを低減

### Slackでの応用場面

- ワークスペースにアプリケーションをインストールする際の認証プロセスで利用
- メッセージ送信やチャンネルの読み取りなど、アプリごとに異なる権限スコープを柔軟に設定可能

# 基本概念

### **リソース所有者（Resource Owner）**

通常、リソースの所有者であるユーザーを指します。保護されたリソースへのアクセス権を持つ主体です。

- Slackであれば、特定のワークスペース内のデータ（チャンネル、メッセージ、ファイルなど）へのアクセス権を持つユーザーがリソース所有者となります。

### **クライアント（Client）**

リソース所有者のデータやサービスにアクセスしたい第三者のアプリケーションです。例えば、ウェブアプリやモバイルアプリが該当します。

- Slackでは、例えば通知を送信するアプリやデータを分析するアプリが該当します。

### **リソースサーバー（Resource Server）**

リソース所有者のデータを保存しているサーバーです。このサーバーは、アクセストークンを受け取ることでデータへのアクセスを許可します。

- Slackではユーザーのメッセージ、チャンネル情報、ファイルなどを保管しています。

### **認可サーバー（Authorization Server）**

リソース所有者の身元を確認し、クライアントにアクセス許可を与えるためのアクセストークンを発行する役割を担うサーバーです。

- ユーザーがアプリを承認すると、Slackの認可サーバーがクライアントにアクセストークンを発行します。

### **アクセストークン（Access Token）**

認可サーバーが発行する「アクセス許可の証明書」のようなものです。クライアントがリソースサーバーにアクセスする際、このトークンを使用して認証を行います。

- Slackでは、このトークンを使ってクライアントがリソースサーバーに認証を行い、保護されたデータにアクセスします。

# OAuth 2.0の流れ (Authorization Code Grant)

具体的な流れを以下の図に参照してください。

```mermaid
sequenceDiagram
    participant Client as クライアント（第三者アプリ）
    participant User as リソース所有者（ユーザー）
    participant AuthServer as 認可サーバー（Slack）
    participant ResourceServer as リソースサーバー（Slack）

    %% (A) Authorization Request
    Client->>User: アクセス許可のリクエスト
    User->>AuthServer: 認可の承認
    %% (B) Authorization Grant (Authorization Code Issued)
    AuthServer-->>Client: 認可コードを発行（リダイレクトURI経由）
    %% (C) Access Token Request
    Client->>AuthServer: 認可コードを使用してアクセストークンを要求
    %% (D) Access Token Issued
    AuthServer-->>Client: アクセストークンを発行
    %% (E) Resource Request
    Client->>ResourceServer: アクセストークンを使用してデータをリクエスト
    %% (F) Resource Response
    ResourceServer-->>Client: データを返す（メッセージ、チャンネル情報など）
```

# Slackでのやり方

以下は、ngrok を使用してローカル環境で Slack アプリの OAuth フローをテストする手順

- ngrok の設定の仕方をこちらから参考できます！

[ngrokの超簡単な利用方法](https://zenn.dev/yh007/articles/427d29d08dabce)

### ステップ 1：ローカルサーバーの起動

Slack からのリダイレクトリクエストを受け取るローカルサーバーを起動します。以下は Python の Flask フレームワークを使った例です。

**Flask のサンプルコード**：

```python
from flask import Flask, request

app = Flask(__name__)

@app.route("/slack/oauth/callback", methods=["GET"])
def slack_callback():
    # Authorization Code を取得
    code = request.args.get("code")
    state = request.args.get("state")

    # 受信データをログに出力
    print(f"Authorization Code: {code}, State: {state}")

    # 必要に応じて、ここでアクセストークンを取得する処理を追加
    return "OAuth Callback Received", 200

if __name__ == "__main__":
    app.run(port=5000)
```

上記コードを保存し、次のコマンドで Flask サーバーを起動：

```bash
python app.py
```

### **ステップ 2：ngrok でローカルサーバーを公開**

以下のコマンドを実行して ngrok を起動し、ローカルサーバーをインターネット経由で公開します：

```bash
ngrok http 5000
```

ngrok が以下のような URL を生成します：

```
https://abc123.ngrok.io
```

### **ステップ 3：Slack アプリのリダイレクト URL を設定**

- 作成した Slack アプリを選択し、**OAuth & Permissions** セクションを開きます。
    
    ![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1006814/85a49b44-8142-9a99-b96c-555b2c77ef5e.png)

    
- **Redirect URLs** に以下を追加：
    
    ```
    https://abc123.ngrok.io/slack/oauth/callback
    ```
    

### ステップ 4：OAuth 認可 URL を構築

- 「Activate Public Distribution」を選択した上、「Sharable URL」からリンクをコピーします。
    
    ![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1006814/4c320724-2db6-7393-fcf0-99be7e18ed23.png)

### **ステップ 5：OAuth フローをテスト**

1. ブラウザで上記の Sharable URL を開きます。
2. Slack のワークスペースを選択し、アプリの権限を承認します。
3. 承認後、Slack はユーザーをリダイレクト URL にリダイレクトし、「Visit Site」をクリックした上、 URL に`code` パラメータを付加します。
4. `code` パラメータに対する値がAuthorization Code となります。
    
    ![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1006814/48ad7232-557d-aee0-8c11-04b792ebb996.png)
    

### **ステップ 6：Authorization Code を使ってアクセストークンを取得**

次に、以下のように `oauth.v2.access` エンドポイントを呼び出してアクセストークンを取得できます。

**リクエスト例**：

```bash
bash
Copy code
curl -X POST https://slack.com/api/oauth.v2.access \
  -F code=<authorization_code> \
  -F client_id=<client_id> \
  -F client_secret=<client_secret> \
  -F redirect_uri=https://abc123.ngrok.io/slack/oauth/callback

```

`client_id`、`client_secret` を以下から確認できると思います。

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1006814/8af5f253-50ba-edbd-c9fa-8f8dd471e552.png)

以上のステップを実行することで、アクセストークンを取得できます。

# まとめ

OAuth 2.0 は、安全かつ柔軟な認可メカニズムを提供しており、特に多者間の協力やオープンプラットフォームの開発において重要な役割を果たします。その核心は認可コードグラント（Authorization Code Grant）にあり、認証とリソースアクセスを分離することで、トークン漏洩のリスクを軽減します。他のグラントタイプも特定のシーンで利用されることがありますが、安全性と汎用性の観点から認可コードグラントが最も推奨されます。