

# IVS 再生トークンの生成と署名
<a name="private-channels-generate-tokens"></a>

JWT およびトークン署名用にサポートされているライブラリの操作の詳細については、[jwt.io](https://jwt.io/) を参照してください。jwt.io インターフェイスでは、プライベートキーを入力してトークンに署名する必要があります。パブリックキーは、トークンを検証する場合にのみ必要です。

## トークンスキーマ
<a name="private-channels-tokens-schema"></a>

すべての JWT には、ヘッダー、ペイロード、署名の 3 つのフィールドがあります。
+ **ヘッダー**は以下を指定します。
  + `alg` は署名アルゴリズムです。これは、SHA-384 ハッシュアルゴリズムを使用する ECDSA 署名アルゴリズムの ES384 です。
  + `typ` はトークン型、JWT です。

  ```
  {
    "alg": "ES384",
    "typ": "JWT"
  }
  ```
+ **ペイロード**には、Amazon IVS 固有のデータが含まれています。
  + `channel-arn` は、動画再生リクエストのリファレンスです。
  + `access-control-allow-origin` は、再生を指定された[オリジン](https://developer.mozilla.org/en-US/docs/Glossary/Origin)に制限するために使用できるオプションのフィールドです。 つまり、指定されたウェブサイトからのみストリームを表示できるようにします。たとえば、誰かが他のウェブサイトにプレイヤーを埋め込むのを防ぐことができます。デフォルトでは、すべてのオリジンで再生が許可されます。(これにより、ブラウザクライアントのみが制限され、ブラウザ以外のクライアントからの再生は制限されません)。このフィールドには、カンマで区切られた複数のオリジンを含めることができます。ワイルドカードドメインが許可されており、各オリジンのホスト名を \* で始めることができます (例: https://\*.amazon.com)。`strict-origin-enforcement` が `true` の場合、最大 5 つのドメインを指定できます。それ以外の場合は、最大値はありません。
  + `strict-origin-enforcement` は、`access-control-allow-origin` フィールドで指定されたオリジンの制限を強化するために使用できるオプションのフィールドです。デフォルトでは、`access-control-allow-origin` 制限はマルチバリアントプレイリストにのみ適用されます。`strict-origin-enforcement` が有効になっている場合、サーバーは、リクエストを実行しているオリジンがすべての再生リクエスト (マルチバリアントプレイリスト、バリアントプレイリスト、およびセグメントを含む) のトークンと一致するという要件を強制します。つまり、すべてのクライアント (ブラウザ以外のクライアントを含む) は、各リクエストで有効なオリジンリクエストヘッダーを提供する必要があります。`setOrigin` メソッドを使用して、IVS iOS および Android プレイヤー SDK でヘッダーを設定します。iOS Safari を除くウェブブラウザでは自動的に設定されます。iOS Safari の場合、オリジンリクエストヘッダーが確実に送信されるように、動画要素に `crossorigin="anonymous"` を追加する必要があります。例えば、`<video crossorigin="anonymous"></video>` などです。
  + `single-use-uuid` は、[トークンの作成時に生成する有効な汎用識別子 (UUID)](https://en.wikipedia.org/wiki/Universally_unique_identifier) を含むオプションのフィールドです。このフィールドと UUID 値を追加すると、生成した関連トークンは、マルチバリアントプレイリストの取得やストリームの視聴に使用された時点で無効になります。一回限りの認証トークンを使用すると、悪意のあるユーザーにとって、プライベートチャネルのストリームを他の視聴者と共有することが難しくなります。`single-use-uuid` クレームを使用する場合、`exp` クレームの最大値は 10 分後になることに注意してください。
  + `viewer-id` は、トークンが付与された視聴者を追跡したり参照したりするのに使用される ID を含むオプションのフィールドです。このフィールドは、今後視聴者の視聴セッションの取り消しを有効にするために必要です。最大長は 40 文字で、値は文字列である必要があります。このフィールドを個人を特定する情報、機密情報、または機密情報には使用しないでください。`viewer-id` を使用する場合、`exp` の最大値は 10 分後になることに注意してください。
  + `viewer-session-version` は、このビューアーセッションに関連付けるバージョンを含むオプションフィールドです。ビューアーセッションを取り消す場合、この値を使用してどのビューアーセッションを取り消すかをフィルタリングできます。たとえば、ここで Unix タイムスタンプを指定すると、指定した時間より前に開始されたすべてのセッションを取り消すことができます。値は 64 ビットの符号付き整数 (Int64) でなければなりません。このフィールドは、`viewer-id` と一緒に (オプションで) 提供されることを意図しており、それ自体は何もしません。デフォルト値は 0 です。
  + `maximum-resolution` により、閲覧者の使用権限に基づいて閲覧者セッションの解像度によるマニフェストフィルタリングを指定できます。たとえば、このフィールドを `HD` に設定すると、閲覧者には `HD` 以下の解像度で表示されます。
  + `ads-opt-out` は、視聴者による広告配信をオプトアウトできるオプションフィールドです。指定できる値は `true` と `fals` です。このフィールドを除外する場合のデフォルト値は `false` です。詳細については、「[Server-Side Ad Insertion](https://docs.aws.amazon.com/ivs/latest/LowLatencyUserGuide/server-side-ad-insertion.html)」を参照してください。
  + `ads-player-params` は、プレイヤーパラメータであるかのように Elemental MediaTailor にパラメータを渡すことができるオプションのフィールドです。このリストに入力したキーは、常に `player_params` テンプレートパラメータとして名前空間化されます。すべてのキーと値の合計ペイロードサイズは 1000 バイトに制限されています。
  + `exp` は、トークンの有効期限を示す Unix UTC タイムスタンプです。これは、ストリームを表示できる時間の長さを示すものではありません。トークンは、ストリーム全体を通してではなく、視聴者が再生を初期化するときに検証されます。この値を整数で入力します。

    Unix タイムスタンプは、うるう秒を無視した、1970-01-01T00:00:00Z UTC から指定された UTC 日付/時刻までの秒数を表す数値であることに注意してください。言語によって、Unix のタイムスタンプはさまざまな単位で測定されます (例: JavaScript の `Date.now()` は時間をミリ秒単位で返します)。([「JWT RFC section 4.1.4」](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4) の「`exp`」を参照してください。)

  ```
  {
      "aws:channel-arn": "<channel_arn>",
      "aws:access-control-allow-origin": "<your-origin>",
      "aws:strict-origin-enforcement": true,
      "aws:single-use-uuid": "<UUID>",
      "aws:viewer-id": "<viewer_id>",
      "aws:viewer-session-version": "<viewer_session_version>",
      "aws:maximum-resolution": "SD" | "HD" | "FULL_HD",
      "exp": <unix timestamp>
  }
  ```
+ **署名**を作成するには、ヘッダー (ES384) で指定されたアルゴリズムを使用して、エンコードされたヘッダーとエンコードされたペイロードに署名します。

  ```
  ECDSASHA384(
    base64UrlEncode(header) + "." +
    base64UrlEncode(payload),
    <private-key>
  )
  ```

## 指示
<a name="private-channels-tokens-instructions"></a>

1. ES384 署名アルゴリズムと、再生キーリソース（上記の `ECDSASHA384` 例を参照）の 1 つに関連付けられているプライベートキーを使用してトークンの署名を生成します。　

1. トークンを組み立てます。

   ```
   base64UrlEncode(header) + "." +
   base64UrlEncode(payload) + "." +
   base64UrlEncode(signature)
   ```

1. 署名付きトークンをクエリパラメータとして、再生 URL に追加します。

   ```
   https://b37c565f6d790a14a0e78afaa6808a80.us-west-2.playback.live-video.net/
   api/video/v1/aws.ivs.us-west-2.123456789.
   channel.fbc789c1-2c56-4ce6-a30a-d99275dc4481.m3u8?token=<token>
   ```

## Node.js の例
<a name="private-channels-tokens-nodejs-example"></a>

以下の内容は、Node.js を使用してバックエンドで (マイクロサービスまたはサーバーレスアプリケーションを介して) トークンを生成する方法の 1 つです。

```
import jwt from "jsonwebtoken";

const getToken = () => {
  const privateChannelArn = process.env.DEMO_PRIVATE_CHANNEL_ARN; // private channel ARN
  const privateChannelPrivateKey = process.env.DEMO_PRIVATE_CHANNEL_PRIVATE_KEY; // playback private key

  const payload = {
    "aws:channel-arn": privateChannelArn,
    "aws:access-control-allow-origin": "*",
    "exp": Date.now() + (60 * 1000), // expires in 1 minute
  };

  const token = jwt.sign(payload, privateChannelPrivateKey, { algorithm: 'ES384' });
  return token;
}
```

フロントエンドアプリケーションでは、以下に示すように、このトークンを取得してプライベートチャネルの再生 URL に追加できます。

```
const streamUrl = `https://b37c565f6d790a14a0e78afaa6808a80.us-west-2.playback.live-video.net/api/video/v1/aws.ivs.us-west-2.123456789.channel.fbc789c1-2c56-4ce6-a30a-d99275dc4481.m3u8?token.m3u8?token=${token}`
const ivsPlayer = IVSPlayer.create();
ivsPlayer.attachHTMLVideoElement(document.getElementById('video-player'));
ivsPlayer.load(streamUrl);
ivsPlayer.play();
```