# 認証ウェブフック

## 概要

Sora 自体はクライアントの接続を認証する機能を持っていません。認証する場合は外部に認証サーバーを用意する必要があります。

Sora はシグナリング経由で送られてきた情報や、
そのチャネルに接続している情報を POST リクエストで `sora.conf` の [auth_webhook_url](SORA_CONF.html#36a99a) に指定された URL へ送信します。
このとき送信する情報は JSON 形式です。

## 注意

シグナリング `"type": "connect"` 経由で送られてきた情報がそのまま認証ウェブフックのリクエストとして送信されるわけではありません。

## ウェブフックリクエスト送信先のサーバーがベーシック認証を利用している場合

もしウェブフックリクエスト送信先のサーバーがベーシック認証を利用している場合は、
`sora.conf` にて [webhook_basic_authn](SORA_CONF.html#081a9f) を `true` に設定することでベーシック認証を利用可能です。

[webhook_basic_authn_user_id](SORA_CONF.html#a107fd) と [webhook_basic_authn_password](SORA_CONF.html#f70fe9) に利用するユーザー ID とパスワードを設定して下さい。


## ウェブフックリクエスト送信先のサーバーが自己署名証明書などを利用している場合

> **注意**
>
> この設定はおすすめしません

デフォルトでは自己署名証明書などの正規の認証局から発行されていない証明書を使用した場合には、信頼できないと判断しエラーになります。

この場合は `sora.conf` にて [webhook_tls_verify_cacert_file](SORA_CONF.html#7036dc) を指定することで、
指定されたルート CA を利用してサーバーの証明書検証を行います。

もしくは推奨はできませんが `sora.conf` にて、
[webhook_insecure](SORA_CONF.html#676769) を `true` に設定することで証明書のチェックを行わなくなります。

## ウェブフックリクエスト送信先のサーバーが mTLS を利用している場合

mTLS を利用する場合は `sora.conf` にて [webhook_tls_fullchain_file](SORA_CONF.html#93f2b9) にクライアント証明書、
[webhook_tls_privkey_file](SORA_CONF.html#7065d6) にクライアント秘密鍵を指定することで mTLS を利用します。

## auth_webhook_url

**デフォルト**: 未設定

クライアントの認証可否を判断するための URL を指定します。認証ウェブフック機能を使用する場合は指定してください。

この URL には HTTPS の URL を指定することも可能です。

HTTPS の URL を指定する場合、リクエスト送信先のアプリケーションについて基本的には正規の認証局から発行された証明書を利用してください。

独自の証明書を利用する場合は [ウェブフックリクエスト送信先のサーバーが自己署名証明書などを利用している場合](AUTH_WEBHOOK.html#467c4b) をご確認ください。

Sora は戻り値の JSON で認証可否を判断します。

HTTP のレスポンスは 200 OK 等の 200 番台のステータスコードの必要があります。

### 設定

認証可否の判断に使用する HTTP リクエストの送信先を `sora.conf` の [auth_webhook_url](SORA_CONF.html#36a99a) に設定します。

```ini
auth_webhook_url = http://127.0.0.1:8080/sora/auth/webhook
```

### 認証処理時に送信する JSON

Sora は、 `sora.conf` の [auth_webhook_url](SORA_CONF.html#36a99a) に設定した URL に対して **POST リクエスト** で次のような JSON を送ります。

```json
{
  "audio": {
    "codec_type": "OPUS"
  },
  "channel_connections": 0,
  "channel_id": "sora",
  "channel_recvonly_connections": 0,
  "channel_sendonly_connections": 0,
  "channel_sendrecv_connections": 0,
  "connection_id": "VSMDDJG3ZH1RHB93W260APVEQW",
  "data_channel_signaling": true,
  "data_channels": [
    {
      "compress": false,
      "direction": "sendrecv",
      "label": "#abc",
      "ordered": true
    }
  ],
  "e2ee": false,
  "ignore_disconnect_websocket": false,
  "label": "WebRTC SFU Sora",
  "multistream": true,
  "node_name": "node1@192.0.2.10",
  "role": "sendrecv",
  "simulcast": false,
  "sora_client": {
    "environment": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36",
    "raw": "Sora JavaScript SDK 2021.1.0",
    "type": "Sora JavaScript SDK",
    "version": "2021.1.0"
  },
  "spotlight": false,
  "timestamp": "2021-06-08T07:51:32.593704Z",
  "version": "2021.1",
  "video": {
    "bit_rate": 1000,
    "codec_type": "VP9"
  }
}
```

`sora.conf` で [legacy_webhook_audio_video_json_structure](SORA_CONF.html#3be597) を false にしている場合は以下のようになります。

```json
{
  "audio": true,
  "audio_codec_type": "OPUS",
  "channel_connections": 0,
  "channel_id": "sora",
  "channel_recvonly_connections": 0,
  "channel_sendonly_connections": 0,
  "channel_sendrecv_connections": 0,
  "connection_id": "VSMDDJG3ZH1RHB93W260APVEQW",
  "data_channel_signaling": true,
  "data_channels": [
    {
      "compress": false,
      "direction": "sendrecv",
      "label": "#abc",
      "ordered": true
    }
  ],
  "e2ee": false,
  "ignore_disconnect_websocket": false,
  "label": "WebRTC SFU Sora",
  "multistream": true,
  "node_name": "node1@192.0.2.10",
  "role": "sendrecv",
  "simulcast": false,
  "sora_client": {
    "environment": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36",
    "raw": "Sora JavaScript SDK 2021.1.0",
    "type": "Sora JavaScript SDK",
    "version": "2021.1.0"
  },
  "spotlight": false,
  "timestamp": "2021-06-08T07:51:32.593704Z",
  "version": "2021.1",
  "video": true,
  "video_bit_rate": 1000,
  "video_codec_type": "VP9"
}
```

- version- Sora のバージョンが `文字列` で入ってきます
- label- `sora.conf` の [label](SORA_CONF.html#815983) で指定した値が入ってきます
- node_name- Sora のノード名が入ってきます
- timestamp- ウェブフックリクエスト送信時のタイムスタンプが RFC3339 フォーマットで入ってきます
  - マイクロ秒まで含まれています
- e2ee- クライアントが E2EE を有効にしているかどうかが入ってきます
  - true の場合は E2EE を利用する接続です
- multistream- マルチストリームでの接続要求を出しているかどうかの値が入ってきます
  - true の場合はマルチストリームを希望している接続です
- simulcast- サイマルキャストでの接続要求を出しているかどうかの値が入ってきます
  - true の場合はサイマルキャストを希望している接続です
- simulcast_rid- サイマルキャストでの受け取る rid を指定します
- spotlight- スポットライトでの接続要求を出しているかどうかの値が入ってきます
- spotlight_number- **この項目はオプションです**
  - `spotlight_number` をシグナリングの connect 時に送ってきた場合に値が入ります
- role- 以下が入ってきます
  - `sendrecv` (送受信)
  - `sendonly` (送信)
  - `recvonly` (受信)
- channel_id- 認証対象のクライアントが接続要求を出しているチャネル ID です
- client_id- 認証対象のクライアントが利用要求を出しているクライアント ID です
  - `"type": "connect"` で `client_id` が送られてこない場合、アプリケーション側にも送られません
- bundle_id- 認証対象のコネクションが利用要求を出しているバンドル ID です
  - `sora.conf` の [signaling_bundle_id](SORA_CONF.html#279311) が `true` で `"type": "connect"` で `bundle_id` が送られてこない場合、アプリケーション側にも送られません
- connection_id- Base32-UUIDv4 です
  - 認証対象のコネクションに割り当てられたユニークな ID です
- channel_connections- 現在そのチャネルの接続数です
  - 自分は含まれません
- channel_sendrecv_connections- 現在そのチャネルで送受信をしている配信者の接続数です
  - 自分は含まれません
- channel_sendonly_connections- 現在そのチャネルで送信のみをしている配信者の接続数です
  - 自分は含まれません
- channel_recvonly_connections- 現在そのチャネルの配信を受信のみしている視聴者の接続数です
  - 自分は含まれません
- audio- `false` の場合は `audio` を使用しません
  - コーデックやビットレートが入ってくる場合は `{"codec_type": "OPUS", "bit_rate": 32}` が入ってきます
  - コーデックの種類は `OPUS` です
  - **ビットレートの項目はオプションです**- もし `default_audio_bit_rate` に値を指定していた場合はその値が利用されます
    - 最小が 6 で、最大が 510 です
  - `sora.conf` の [legacy_webhook_audio_video_json_structure](SORA_CONF.html#3be597) を `false` にした場合以下のようにフラット化します- `audio: true`
    - `audio_codec_type: "OPUS"`
    - `audio_bit_rate: 32`
    - 詳細は [ウェブフックの audio と video 項目の JSON 構造のフラット化](WEBHOOK_AUDIO_VIDEO_FLATTEN_JSON.html) をご確認ください
- video- `false` の場合は `video` を使用しません
  - コーデックやビットレートが入ってくる場合は `{"codec_type": "VP9", "bit_rate": 500}` が入ってきます
  - コーデックの種類は VP8、VP9、AV1、H264、H265 の 5 種類です
  - コーデックはクライアントが送ってこない場合はデフォルトで `VP9` が使用されます
  - ビットレートはクライアントが送ってこない場合は `sora.conf` の [default_video_bit_rate](SORA_CONF.html#620132) が使用されます- デフォルトは 500 です
    - 最小が 1 で、最大が 30000 です
    - 15000 より大きい値は現時点でサポート範囲外です
    - 単位は `kbps` です
  - `sora.conf` の [legacy_webhook_audio_video_json_structure](SORA_CONF.html#3be597) を `false` にした場合以下のようにフラット化します- `"video": true`
    - `"video_codec_type": "VP9"`
    - `"video_bit_rate": 500`
    - 詳細は [ウェブフックの audio と video 項目の JSON 構造のフラット化](WEBHOOK_AUDIO_VIDEO_FLATTEN_JSON.html) をご確認ください
- metadata- **この項目はオプションです**
  - ユーザーが定義を自由にできる値です
  - JSON で使用できる形式ならどんな値でも指定可能です
  - `"type": "connect"` で `metadata` が送られてこない場合、アプリケーション側にも送られません
- authn_metadata- **この項目はオプションです**
  - この項目は metadata と同じです
  - metadata の別名です
  - `"type": "connect"` で `metadata` が送られてこない場合、アプリケーション側にも送られません
- data_channel_signaling- シグナリングの DataChannel 切り替えをするかどうか
- ignore_disconnect_websocket- シグナリングの DataChannel 切り替え時に WebSocket の切断を無視するかどうか
- data_channels- **この項目はオプションです**
  - DataChannel を利用したメッセージングの定義が入ってきます
  - クライアントが指定しない場合は入ってきません
- sora_client- **この項目はオプションです**
  - クライアントから送られてきた情報が入ってきます

### sora_client

認証ウェブフックの `sora_client` にはクライアントから送られてきた情報が入ってきます。
クライアントから情報が送られてこなければ含まれません。 Sora SDK を利用している場合は必ず入ってきます。

```json
"sora_client": {
  "environment": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36",
  "raw": "Sora JavaScript SDK 2021.1.0",
  "type": "Sora JavaScript SDK",
  "version": "2021.1.0"
},
```

- type- オプションです
  - クライアントから送られてきた Sora SDK またはクライアントのタイプが入ってきます
- raw- オプションです
  - クライアントから送られてきた sora_client の値がそのまま入ってきます
- version- オプションです
  - クライアントから送られてきた Sora SDK またはクライアントのバージョンが入ってきます
- commit_short- オプションです
  - クライアントから送られてきた Sora SDK のコミットハッシュが入ってきます
- environment- オプションです
  - クライアントから送られてきた端末情報が入ってきます
- libwebrtc- オプションです
  - クライアントから送られてきた libwebrtc のバージョン情報が入ってきます

### 認証成功時のレスポンス JSON

認証に成功した場合は、以下の JSON を返してください。

```json
{
    "allowed": true
}
```

Sora は "allowed" が true の場合は認証を成功と判断して処理をします。

### 認証失敗時のレスポンス JSON

認証に失敗した場合は、以下の JSON を返してください。

```json
{
    "allowed": false,
    "reason": "<String>"
}
```

> **注釈**
>
> 認証失敗の場合も HTTP レスポンスのステータスコードは 200 番台である必要があります

Sora は "allowed" が false で、 "reason" が含まれている場合に認証失敗と判断して処理します。

"reason" は必須です、何かしらエラー理由を **100 バイト以内** の文字列にて追加してください。

認証に失敗した場合、認証サーバーから送られてきた "reason" の内容は文字列としてクライアントに送られます。


```
"<認証サーバーから送られてきた reason>"
```

## 認証ウェブフック成功時の払い出し

認証サーバーは認証成功時に様々な値を出すことができます。

```json
{
    "allowed": true,
    "event_metadata": {
      "pk": 1
    }
}
```

詳細は [認証ウェブフック成功時の払い出し](AUTH_WEBHOOK_RETURN.html) をご確認ください。


## 認証ウェブフックログ

`sora.conf` の [auth_webhook_log](SORA_CONF.html#116686) を `true` にしている場合は `log/auth_webhook.log` が出力されます。

> **重要**
>
> `auth_webhook_log` はデフォルトで `true` です。

このログには認証ウェブフックのリクエストとレスポンス、ウェブフック URL、タイムスタンプが含まれます。

- req- 認証ウェブフックの送信リクエストがそのまま入ります
- res- 認証ウェブフックの戻り値がそのまま入ります
- url- auth_webhook_url を指定していない場合はログに含まれません
- timestamp- RFC3339 フォーマットのタイムスタンプが入ります
  - UTC です

### auth_webhook_url あり / レスポンスあり

```json
{
  "req": {
    "audio": {
      "codec_type": "OPUS"
    },
    "channel_connections": 0,
    "channel_id": "sora",
    "channel_recvonly_connections": 0,
    "channel_sendonly_connections": 0,
    "channel_sendrecv_connections": 0,
    "connection_id": "F2SMT1W59S5ADDZ84CMQ8CDBX4",
    "e2ee": false,
    "label": "WebRTC SFU Sora",
    "multistream": true,
    "node_name": "node1@192.0.2.10",
    "role": "sendrecv",
    "simulcast": false,
    "sora_client": {
      "environment": "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_0_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36",
      "raw": "Sora JavaScript SDK 2020.5.0",
      "type": "Sora JavaScript SDK",
      "version": "2020.5.0"
    },
    "spotlight": false,
    "timestamp": "2020-12-07T09:16:54.079650Z",
    "version": "2020.3",
    "video": {
      "bit_rate": 1000,
      "codec_type": "VP9"
    }
  },
  "res": {
    "allowed": true,
    "event_metadata": {
      "abc": "efg"
    },
    "metadata": "abc",
    "signaling_notify_metadata": {
      "a": "b"
    }
  },
  "timestamp": "2020-12-07T09:16:54.089962Z",
  "url": "http://127.0.0.1:3001/sora/auth/webhook"
}
```

### auth_webhook_url あり / レスポンスなし

- res がありません

```json
{
  "req": {
    "audio": {
      "codec_type": "OPUS"
    },
    "channel_connections": 0,
    "channel_id": "sora",
    "channel_recvonly_connections": 0,
    "channel_sendonly_connections": 0,
    "channel_sendrecv_connections": 0,
    "connection_id": "0FBC8HF84544ZDHYYN9BCRNZG8",
    "e2ee": false,
    "label": "WebRTC SFU Sora",
    "multistream": true,
    "node_name": "node1@192.0.2.10",
    "role": "sendrecv",
    "simulcast": false,
    "sora_client": {
      "environment": "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_0_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36",
      "raw": "Sora JavaScript SDK 2020.5.0",
      "type": "Sora JavaScript SDK",
      "version": "2020.5.0"
    },
    "spotlight": false,
    "timestamp": "2020-12-07T06:30:56.240917Z",
    "version": "2020.3",
    "video": {
      "bit_rate": 1000,
      "codec_type": "VP9"
    }
  },
  "timestamp": "2020-12-07T06:30:56.252785Z",
  "url": "http://127.0.0.1:3001/sora/authn/webhook"
}
```

### auth_webhook_url なし

- url がありません

```json
{
  "req": {
    "audio": {
      "codec_type": "OPUS"
    },
    "channel_connections": 0,
    "channel_id": "sora",
    "channel_recvonly_connections": 0,
    "channel_sendonly_connections": 0,
    "channel_sendrecv_connections": 0,
    "client_id": "K8PCW533MN1WK24YNZ83HDP74C",
    "connection_id": "K8PCW533MN1WK24YNZ83HDP74C",
    "e2ee": false,
    "label": "WebRTC SFU Sora",
    "multistream": true,
    "node_name": "node1@192.0.2.10",
    "role": "sendrecv",
    "simulcast": false,
    "sora_client": {
      "environment": "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_0_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36",
      "raw": "Sora JavaScript SDK 2020.5.0",
      "type": "Sora JavaScript SDK",
      "version": "2020.5.0"
    },
    "spotlight": false,
    "timestamp": "2020-12-07T06:26:58.916204Z",
    "version": "2020.3",
    "video": {
      "bit_rate": 1000,
      "codec_type": "VP9"
    }
  },
  "res": {
    "allowed": true
  },
  "timestamp": "2020-12-07T06:26:58.916242Z"
}
```

## エラーメッセージ

これらエラーメッセージは sora.log に出力されます。

### AUTH_WEBHOOK_RESPONSE_UNEXPECTED_STATUS_CODE

認証サーバーが返すステータスコードが 200 系ではなかった場合に出力されます。

例えばステータスコードが 400 だと出力されます。

### INVALID_AUTH_WEBHOOK_RESPONSE_JSON

認証サーバーが返す JSON に必須で項目が含まれていない場合に出力されます。

例えば `allowed` が含まれていない場合に出力されます。

### AUTH-WEBHOOK-RESPONSE-BAD-JSON

認証サーバーが返す JSON のデコードに失敗した場合に出力されます。

例えば `{"a: b"}` といったような JSON と判断できない場合に出力されます。


## シーケンス図


### 認証成功

seqdiag {
    default_fontsize = 15;
    edge_length = 250;

    クライアント ->> Sora [label = '"type": "connect"'];
        Sora -> アプリケーションサーバー [label = '認証ウェブフック'];
        Sora <-- アプリケーションサーバー [label = '200 OK\n{"allowed": true}'];
    クライアント <<- Sora [label = '"type": "offer"'];
    クライアント ->> Sora [label = '"type": "answer"', noactivate];

    === WebRTC 確立 ===
}


### 認証拒否

seqdiag {
    default_fontsize = 15;
    edge_length = 250;

    クライアント ->> Sora [label = '"type": "connect"'];
        Sora -> アプリケーションサーバー [label = '認証ウェブフック'];
        Sora <-- アプリケーションサーバー [label = '200 OK\n{"allowed": false, \n"reason": "reject"}'];
    クライアント <<- Sora [label = 'WebSocket Close'];
}
