

# Gerar e assinar tokens de reprodução do IVS
<a name="private-channels-generate-tokens"></a>

Para obter detalhes sobre como trabalhar com JWTs e as bibliotecas suportadas para assinar tokens, visite [jwt.io](https://jwt.io/). Na interface do jwt.io, é necessário inserir sua chave privada para assinar os tokens. A chave pública será necessária somente se você quiser verificar os tokens.

## Esquema de token
<a name="private-channels-tokens-schema"></a>

Todos os JWTs têm três campos: cabeçalho, carga útil e assinatura.
+ O **cabeçalho** especifica:
  + `alg` é o algoritmo de assinatura. Este é o ES384, um algoritmo de assinatura ECDSA que usa o algoritmo de hash SHA-384.
  + `typ` é o tipo de token, JWT.

  ```
  {
    "alg": "ES384",
    "typ": "JWT"
  }
  ```
+ A **carga útil** contém dados específicos do Amazon IVS:
  + `channel-arn` é uma referência para a solicitação de reprodução de vídeo.
  + `access-control-allow-origin` é um campo opcional que pode ser usado para restringir a reprodução a uma [origem](https://developer.mozilla.org/en-US/docs/Glossary/Origin) especificada, isto é, para tornar uma transmissão visível em apenas um site especificado. Por exemplo, talvez você queira impedir que as pessoas incorporem o player em outros sites. Por padrão, a reprodução é permitida em todas as origens. (Observe que isso restringe apenas o cliente do navegador; isso não restringe a reprodução de um cliente que não seja do navegador.) Esse campo pode conter várias origens, separando-se por vírgulas. Domínios curinga são permitidos: cada origem pode começar seu nome de host com \* (exemplo: https://\*.amazon.com). Se `strict-origin-enforcement` for `true`, no máximo 5 domínios podem ser especificados; caso contrário, não há máximo.
  + `strict-origin-enforcement` é um campo opcional que pode ser usado para fortalecer a restrição de origem especificada no campo `access-control-allow-origin`. Por padrão, a restrição `access-control-allow-origin` se aplica somente à lista de reprodução multivariante. Se `strict-origin-enforcement` estiver habilitado, o servidor exigirá que a origem da solicitação corresponda ao token para todas as solicitações de reprodução (incluindo lista de reprodução multivariante, lista de reprodução variante e segmentos). Isso significa que todos os clientes (incluindo clientes que não são navegadores) precisarão fornecer um cabeçalho de solicitação de origem válido com cada solicitação. Use o método `setOrigin` para definir o cabeçalho nos SDKs dos reprodutores IVS para iOS e Android. Ele é definido automaticamente em navegadores da Web, exceto o iOS Safari. Para o iOS Safari, você precisa adicionar `crossorigin="anonymous"` ao elemento de vídeo para garantir que o cabeçalho da solicitação de origem seja enviado. Exemplo: `<video crossorigin="anonymous"></video>`. 
  + `single-use-uuid` é um campo opcional que contém um [identificador universal exclusivo (UUID)](https://en.wikipedia.org/wiki/Universally_unique_identifier) válido que você gera como parte da criação do token. Se você adicionar esse campo e um valor de UUID, o token associado gerado será invalidado quando for usado para buscar uma lista de reprodução multivariada e assistir a uma transmissão. Os tokens de autenticação de uso único dificultam para usuários mal-intencionados compartilharem uma transmissão em seus canais privados com outros visualizadores. Observe que ao usar a reivindicação `single-use-uuid`, o valor máximo para a reivindicação `exp` é de dez minutos no futuro.
  + `viewer-id` é um campo opcional que contém uma ID usada para rastrear e fazer referência ao visualizador a quem o token foi concedido. Este campo é necessário para habilitar a capacidade de revogar a sessão de visualização do visualizador no futuro. O tamanho máximo é de 40 caracteres e o valor deve ser qualificado como uma string. Não use este campo para identificação pessoal, informações confidenciais ou sigilosas. Observe que ao usar o `viewer-id`, o valor máximo para `exp` é de dez minutos no futuro.
  + `viewer-session-version` é um campo opcional que contém uma versão a ser associada a esta sessão do visualizador. Ao revogar sessões do visualizador, este valor pode ser usado para filtrar quais sessões do visualizador serão revogadas. Por exemplo, especificar um timestamp Unix aqui permitiria a revogação de todas as sessões iniciadas antes do horário especificado. O valor deve ser um número inteiro assinado de 64 bits (Int64). Este campo deve ser fornecido (opcionalmente) junto com o `viewer-id`; ele não faz nada sozinho. O valor padrão é 0.
  + `maximum-resolution` permite especificar a filtragem de manifesto por resolução para uma sessão de espectador, com base nas permissões do espectador. Por exemplo, definir esse campo como `HD` significa que o visualizador receberá uma resolução menor ou igual a `HD`.
  + `ads-opt-out` é um campo opcional que permite excluir um espectador do recebimento de anúncios. Os valores permitidos são `true` e `fals`e. O valor padrão quando este campo é excluído é `false`. Consulte [Inserção de anúncios no lado do servidor](https://docs.aws.amazon.com/ivs/latest/LowLatencyUserGuide/server-side-ad-insertion.html) para obter mais informações.
  + `ads-player-params` é um campo opcional que permite passar parâmetros para o Elemental MediaTailor como se fossem parâmetros do reprodutor. As chaves que você incluir nesta lista sempre farão parte do namespace de parâmetros do modelo `player_params`. O tamanho total da carga útil de todas as chaves e valores combinados é limitado a 1000 bytes.
  + `exp` é um timestamp UTC do Unix para o momento em que o token expirar. Isso não indica o período em que o stream pode ser visualizado. O token é validado quando o visualizador inicializa a reprodução, não em todo o stream. Insira esse valor como um valor de tipo inteiro.

    Observe que um timestamp Unix corresponde a um valor numérico que representa o número de segundos de 1970-01-01T00:00:00Z UTC até a data/hora UTC especificada, ignorando os segundos bissextos. Linguagens diferentes medem timestamps Unix em unidades diferentes; por exemplo, `Date.now()` do JavaScript retorna a hora em milissegundos. (Consulte `exp` na [JWT RFC section 4.1.4](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4).)

  ```
  {
      "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>
  }
  ```
+ Para criar a **assinatura**, use a chave privada com o algoritmo especificado no cabeçalho (ES384) para assinar o cabeçalho codificado e a carga útil codificada.

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

## Instruções
<a name="private-channels-tokens-instructions"></a>

1. Gere a assinatura do token com o algoritmo de assinatura ES384 e uma chave privada que é associada a um de seus recursos de chave de reprodução (consulte o exemplo `ECDSASHA384` acima).

1. Monte o token.

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

1. Acrescente o token assinado ao URL de reprodução como um parâmetro de consulta.

   ```
   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>
   ```

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

Abaixo está uma forma de gerar um token no back-end (por meio de um microsserviço ou aplicação com tecnologia sem servidor) usando o Node.js. 

```
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;
}
```

Em sua aplicação de frontend, você pode recuperar esse token e anexá-lo à URL de reprodução do canal privado, conforme mostrado abaixo. 

```
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();
```