サポートに連絡する| システムステータス
ページコンテンツ

    JSON Web トークン (JWT)

    の作成このトピックでは、との通信時に使用できる JSON Web トークン (JWT) の作成方法を学習します。ブライトコーブプレイバック API。

    はじめに

    ビデオライブラリへのアクセス時に追加の保護レベルを追加したり、コンテンツにユーザーレベルの制限を適用したりするには、Brightcove Playback API の呼び出しで JSON Web トークン (JWT) を渡すことができます。トークンを作成するには、次の手順を実行します。

    1. 公開鍵と秘密キーのペアを生成する
    2. Brightcoveに公開鍵を登録する
    3. JSON ウェブトークンの作成
    4. テスト再生

    公開鍵と秘密鍵のペアを生成

    公開者は公開鍵と秘密鍵ペアを生成し、その公開鍵をブライトコーブに提供します。秘密鍵はパブリッシャーがトークンの署名に使用し、ブライトコーブと共有されません。

    公開鍵と秘密鍵のペアを生成する方法は多数あります。以下にいくつかの例を挙げます。

    bash スクリプトの例:

    キーペアを生成するスクリプト例:

    #!/bin/bash
    set -euo pipefail
    
    NAME=${1:-}
    test -z "${NAME:-}" && NAME="brightcove-playback-auth-key-$(date +%s)"
    mkdir "$NAME"
    
    PRIVATE_PEM="./$NAME/private.pem"
    PUBLIC_PEM="./$NAME/public.pem"
    PUBLIC_TXT="./$NAME/public_key.txt"
    
    ssh-keygen -t rsa -b 2048 -m PEM -f "$PRIVATE_PEM" -q -N ""
    openssl rsa -in "$PRIVATE_PEM" -pubout -outform PEM -out "$PUBLIC_PEM" 2>/dev/null
    openssl rsa -in "$PRIVATE_PEM" -pubout -outform DER | base64 > "$PUBLIC_TXT"
    
    rm "$PRIVATE_PEM".pub
    
    echo "Public key to saved in $PUBLIC_TXT"
    

    スクリプトを実行します。

    $ bash keygen.sh
    
    Go の使用例

    Goプログラミング言語を使用してキーペアを生成する例:

    package main
      
      import (
        "crypto/rand"
        "crypto/rsa"
        "crypto/x509"
        "encoding/base64"
        "encoding/pem"
        "flag"
        "fmt"
        "io/ioutil"
        "os"
        "path"
        "strconv"
        "time"
      )
      
      func main() {
        var out string
      
        flag.StringVar(&out, "output-dir", "", "Output directory to write files into")
        flag.Parse()
      
        if out == "" {
          out = "rsa-key_" + strconv.FormatInt(time.Now().Unix(), 10)
        }
      
        if err := os.MkdirAll(out, os.ModePerm); err != nil {
          panic(err.Error())
        }
      
        priv, err := rsa.GenerateKey(rand.Reader, 2048)
        if err != nil {
          panic(err.Error())
        }
      
        privBytes := x509.MarshalPKCS1PrivateKey(priv)
      
        pubBytes, err := x509.MarshalPKIXPublicKey(priv.Public())
        if err != nil {
          panic(err.Error())
        }
      
        privOut, err := os.OpenFile(path.Join(out, "private.pem"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
        if err != nil {
          panic(err.Error())
        }
      
        if err := pem.Encode(privOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: privBytes}); err != nil {
          panic(err.Error())
        }
      
        pubOut, err := os.OpenFile(path.Join(out, "public.pem"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
        if err != nil {
          panic(err.Error())
        }
      
        if err := pem.Encode(pubOut, &pem.Block{Type: "PUBLIC KEY", Bytes: pubBytes}); err != nil {
          panic(err.Error())
        }
      
        var pubEnc = base64.StdEncoding.EncodeToString(pubBytes)
      
        var pubEncOut = path.Join(out, "public_key.txt")
        if err := ioutil.WriteFile(pubEncOut, []byte(pubEnc+"\n"), 0600); err != nil {
          panic(err.Error())
        }
      
        fmt.Println("Public key saved in " + pubEncOut)
      }
      
    node.js の使用例

    node.js を使用してキーペアを生成する例:

    var crypto = require("crypto");
      var fs = require("fs");
      
      var now = Math.floor(new Date() / 1000);
      var dir = "rsa-key_" + now;
      fs.mkdirSync(dir);
      
      crypto.generateKeyPair(
        "rsa",
        {modulusLength: 2048},
        (err, publicKey, privateKey) => {
          fs.writeFile(
            dir + "/public.pem",
            publicKey.export({ type: "spki", format: "pem" }),
            err => {}
          );
          fs.writeFile(
            dir + "/public_key.txt",
            publicKey.export({ type: "spki", format: "der" }).toString("base64") +
              "\n",
            err => {}
          );
          fs.writeFile(
            dir + "/private.pem",
            privateKey.export({ type: "pkcs1", format: "pem" }),
            err => {}
          );
        }
      );
      
      console.log("Public key saved in " + dir + "/public_key.txt");

    公開鍵を登録する

    Key API を使用して、パブリックキーをブライトコーブに登録します。

    キーAPI

    Key API は、ブライトコーブで公開キーを管理するために使用されます。

    ベース URL

    API のベース URL は次のとおりです。

    https://playback-auth.api.brightcove.com

    アカウントパス

    いずれの場合も、特定の Video Cloud アカウントに対してリクエストが行われます。したがって、あなたは常にベースURLにアカウントIDが続く用語アカウントを追加します。

    https://playback-auth.api.brightcove.com/v1/accounts/{accountID}

    認可

    リクエストのアクセストークンが必要であり、Authorizationヘッダに存在する必要があります።

    Authorization: Bearer {access_token}

    アクセストークンは、一時的な OAuth2 アクセストークンで、Brightcove OAuth サービスから取得する必要があります。クライアント資格情報を取得し、アクセストークンを取得する方法の詳細については、ブライトコーブ OAuth の概要を参照してください

    パーミッション

    Key API へのリクエストは、次の権限を持つクライアント認証情報から行う必要があります。

    • video-cloud/playback-auth/key/read
    • video-cloud/playback-auth/key/write

    キーを管理する

    キー API は、次のリクエストをサポートします。

    新しいキーを登録します。

    API リクエスト本文に公開鍵の値を入力します。このキーは public_key.txtファイルにあります。

    リクエスト
    POST /v1/accounts/{accountID}/keys
        Content-Type: application/json
        Body: {"value": "MFkwEwYHKoZIzj0CAQYIKoZIzj...MyeQviqploA=="}
    
    カールの使用
    curl -X POST \\ -H "Content-Type:application / json" \\ -H "認証:ベアラー{access_token} "\-d ' {"value": "{your_public_key_value}「}'  \ https://playback-auth.api.brightcove.com/v1/accounts/ {accountID} /keys
    応答
    {
      "id": "{your_public_key_id}",
      "type": "public",
      "algorithm": "rsa",
      "value": "{your_public_key_value}",
      "createdAt": "2020-01-03T20:30:36.488Z"
    }

    キーをリストする:

    アカウント内の公開鍵のリストを取得します。

    GET /v1/accounts/{accountID}/keys

    キーを 1 つ取得する:

    アカウントの公開鍵の詳細を取得します。

    GET /v1/accounts/{accountID}/keys/{key_Id}

    キーを 1 つ削除する:

    アカウントの公開鍵を削除します。

    DELETE /v1/accounts/{accountID}/keys/{key_Id}

    JSON ウェブトークンの作成

    パブリッシャーは JSON ウェブトークン (JWT) を作成します。トークンは、SHA-256ハッシュアルゴリズム(JWT仕様では「」として識別されるRSAアルゴリズムで署名されています。 RS256 ")他のJWTアルゴリズムはサポートされません。

    標準的な JSON Web トークンのクレームのサブセットと、ブライトコーブによって定義されたいくつかのプライベートクレームが使用されます。を作成しますJSONWebトークン秘密鍵で署名しました。

    静的 URL 配信のクレーム

    Brightcoveの静的 URL 配信では、次のクレームを使用できます。

    フィールド タイプ 必須 説明
    accid ストリング 再生中のコンテンツを所有するアカウント ID
    drules 文字列 [] 適用する配信ルールのアクション ID のリスト。詳細については、「配信ルールの実装」を参照してください。config_id クエリパラメータも設定されている場合、この要求がオーバーライドされるため、無視されます。
    exp 整数 このトークンが有効でなくなる時間(エポックからの秒単位)。から 30 日以内にする必要があります。iat
    iat 整数 このトークンが発行された時間(エポックからの秒単位)
    conid ストリング 存在する場合、このトークンは特定の Video Cloud ビデオ ID のライセンス取得のみを許可します。

    有効な動画IDである必要があります。参照IDはサポートされていないことに注意してください。
    pro ストリング 1 つのビデオで複数のビデオを使用できる場合の保護タイプを指定します。

    値:
    • 「」(コンテンツをクリアするためのデフォルト)
    • 「aes128"
    • 「Widevine」
    • 「playready」
    • フェアプレイ
    vod オブジェクト ビデオオンデマンドの特定の設定オプションが含まれています。
    vod.ssai ストリング サーバーサイド広告挿入 (SSAI) の設定ID。この要求は、HLS または DASH VMAP のいずれかを取得するために必要です

    以下に、使用できる JSON Web トークン (JWT) の主張の例を示します。

    {
    // account id: JWT is only valid for this accounts
    "accid":"4590388311111",
    // drules: list of delivery rule IDs to be applied
    "drules": ["0758da1f-e913-4f30-a587-181db8b1e4eb"]
    // expires: timestamp when JWT expires
    "exp":1577989732,
    // issued at: timestamp when the JWT was created
    "iat":1575484132,
    // content id: JWT is only valid for video ID
    "conid":"5805807122222",
    // protection: specify a protection type in the case where multiple are available for a single video
    "pro":"aes128",
    // VOD specific configuration options
    "vod":{
    // SSAI configuration to apply
    "ssai":"efcc566-b44b-5a77-a0e2-d33333333333"
    }
    }

    トークンを生成する

    JWTトークンを生成するためのライブラリは一般的に利用可能です。詳細については、 JSON Webトークンのサイトを参照してください。

    bash スクリプトの例:

    JWT トークンを生成するスクリプト例:

    #! /usr/bin/env bash
    # Static header fields.
    HEADER='{
    	"type": "JWT",
    	"alg": "RS256"
    }'
    
    payload='{
    	"accid": "{your_account_id}"
    }'
    
    # Use jq to set the dynamic `iat` and `exp`
    # fields on the payload using the current time.
    # `iat` is set to now, and `exp` is now + 1 second.
    PAYLOAD=$(
    	echo "${payload}" | jq --arg time_str "$(date +%s)" \
    	'
    	($time_str | tonumber) as $time_num
    	| .iat=$time_num
    	| .exp=($time_num + 60 * 60)
    	'
    )
    
    function b64enc() { openssl enc -base64 -A | tr '+/' '-_' | tr -d '='; }
    
    function rs_sign() { openssl dgst -binary -sha256 -sign playback-auth-keys/private.pem ; }
    
    JWT_HDR_B64="$(echo -n "$HEADER" | b64enc)"
    JWT_PAY_B64="$(echo -n "$PAYLOAD" | b64enc)"
    UNSIGNED_JWT="$JWT_HDR_B64.$JWT_PAY_B64"
    SIGNATURE=$(echo -n "$UNSIGNED_JWT" | rs_sign | b64enc)
    
    echo "$UNSIGNED_JWT.$SIGNATURE"
    

    スクリプトを実行します。

    $ bash jwtgen.sh
    

    Go の使用例

    サードパーティライブラリを使用せずにトークンを生成するための (CLI ツールとして) リファレンス Go実装の例を次に示します。

    package main
    
    import (
    	"crypto"
    	"crypto/ecdsa"
    	"crypto/rand"
    	"crypto/rsa"
    	"crypto/sha256"
    	"crypto/x509"
    	"encoding/base64"
    	"encoding/json"
    	"encoding/pem"
    	"flag"
    	"fmt"
    	"io/ioutil"
    	"os"
    	"strings"
    	"time"
    )
    
    // Header is the base64UrlEncoded string of a JWT header for the RS256 algorithm
    const RSAHeader = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9"
    
    // Header is the base64UrlEncoded string of a JWT header for the EC256 algorithm
    const ECHeader = "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9"
    
    // Claims represents constraints that should be applied to the use of the token
    type Claims struct {
    	Iat   float64 `json:"iat,omitempty"`   // Issued At
    	Exp   float64 `json:"exp,omitempty"`   // Expires At
    	Accid string  `json:"accid,omitempty"` // Account ID
    	Conid string  `json:"conid,omitempty"` // Content ID
    	Maxu  float64 `json:"maxu,omitempty"`  // Max Uses
    	Maxip float64 `json:"maxip,omitempty"` // Max IPs
    	Ua    string  `json:"ua,omitempty"`    // User Agent
    }
    
    func main() {
    	var key, algorithm string
    
    	c := Claims{Iat: float64(time.Now().Unix())}
    
    	flag.StringVar(&key, "key", "", "Path to private.pem key file")
    	flag.StringVar(&c.Accid, "account-id", "", "Account ID")
    	flag.StringVar(&c.Conid, "content-id", "", "Content ID (eg, video_id or live_job_id)")
    	flag.Float64Var(&c.Exp, "expires-at", float64(time.Now().AddDate(0, 0, 1).Unix()), "Epoch timestamp (in seconds) for when the token should stop working")
    	flag.Float64Var(&c.Maxu, "max-uses", 0, "Maximum number of times the token is valid for")
    	flag.Float64Var(&c.Maxip, "max-ips", 0, "Maximum number of unique IP addresses the token is valid for")
    	flag.StringVar(&c.Ua, "user-agent", "", "User Agent that the token is valid for")
    	flag.StringVar(&algorithm, "algo", "", "Key algorithm to use for signing. Valid: ec256, rsa256")
    	flag.Parse()
    
    	if key == "" {
    		fmt.Printf("missing required flag: -key\n\n")
    		flag.Usage()
    		os.Exit(1)
    	}
    
    	if algorithm == "" {
    		fmt.Printf("missing required flag: -algo\n\n")
    		flag.Usage()
    		os.Exit(2)
    	}
    
    	if algorithm != "rsa256" && algorithm != "ec256" {
    		fmt.Printf("missing valid value for -algo flag. Valid: rsa256, ec256\n\n")
    		flag.Usage()
    		os.Exit(3)
    	}
    
    	if c.Accid == "" {
    		fmt.Printf("missing required flag: -account-id\n\n")
    		flag.Usage()
    		os.Exit(4)
    	}
    
    	bs, err := json.Marshal(c)
    	if err != nil {
    		fmt.Println("failed to marshal token to json", err)
    		os.Exit(5)
    	}
    
    	kbs, err := ioutil.ReadFile(key)
    	if err != nil {
    		fmt.Println("failed to read private key", err)
    		os.Exit(6)
    	}
    
    	if algorithm == "rsa256" {
    		processRSA256(kbs, bs)
    	} else {
    		processEC256(kbs, bs)
    	}
    }
    
    func processRSA256(kbs, bs []byte) {
    	block, _ := pem.Decode(kbs)
    	if block == nil {
    		fmt.Println("failed to decode PEM block containing private key")
    		os.Exit(7)
    	}
    
    	if block.Type != "RSA PRIVATE KEY" {
    		fmt.Println("failed to decode PEM block containing private key")
    		os.Exit(8)
    	}
    
    	pKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
    	if err != nil {
    		fmt.Println("failed to parse rsa private key", err)
    		os.Exit(9)
    	}
    
    	message := RSAHeader + "." + base64.RawURLEncoding.EncodeToString(bs)
    
    	hash := crypto.SHA256
    	hasher := hash.New()
    	_, _ = hasher.Write([]byte(message))
    	hashed := hasher.Sum(nil)
    
    	r, err := rsa.SignPKCS1v15(rand.Reader, pKey, hash, hashed)
    	if err != nil {
    		fmt.Println("failed to sign token", err)
    		os.Exit(10)
    	}
    
    	sig := strings.TrimRight(base64.RawURLEncoding.EncodeToString(r), "=")
    
    	fmt.Println(message + "." + sig)
    }
    
    func processEC256(kbs, bs []byte) {
    	block, _ := pem.Decode(kbs)
    	if block == nil {
    		fmt.Println("failed to decode PEM block containing private key")
    		os.Exit(7)
    	}
    
    	if block.Type != "EC PRIVATE KEY" {
    		fmt.Println("failed to decode PEM block containing private key")
    		os.Exit(8)
    	}
    
    	pkey, err := x509.ParseECPrivateKey(block.Bytes)
    	if err != nil {
    		fmt.Println("failed to parse ec private key", err)
    		os.Exit(9)
    	}
    
    	message := ECHeader + "." + base64.RawURLEncoding.EncodeToString(bs)
    	hash := sha256.Sum256([]byte(message))
    
    	r, s, err := ecdsa.Sign(rand.Reader, pkey, hash[:])
    	if err != nil {
    		fmt.Println("failed to sign token", err)
    		os.Exit(10)
    	}
    
    	curveBits := pkey.Curve.Params().BitSize
    
    	keyBytes := curveBits / 8
    	if curveBits%8 > 0 {
    		keyBytes++
    	}
    
    	rBytes := r.Bytes()
    	rBytesPadded := make([]byte, keyBytes)
    	copy(rBytesPadded[keyBytes-len(rBytes):], rBytes)
    
    	sBytes := s.Bytes()
    	sBytesPadded := make([]byte, keyBytes)
    	copy(sBytesPadded[keyBytes-len(sBytes):], sBytes)
    
    	out := append(rBytesPadded, sBytesPadded...)
    
    	sig := base64.RawURLEncoding.EncodeToString(out)
    	fmt.Println(message + "." + sig)
    }
    

    結果

    https://JWT.io を使用してデコードされたトークンの例を以下に示します。クレームの全セットを指定します。

    ヘッダー:

    {
      "alg": "RS256",
      "type": "JWT"
    }
    

    ペイロード:

    {
      "accid": "1100863500123",
      "conid": "51141412620123",
      "exp": 1554200832,
      "iat": 1554199032,
      "maxip": 10,
      "maxu": 10,
      "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36"
    }
    

    テスト再生

    必須ではありませんが、プレーヤーを設定する前にビデオ再生をテストすることをお勧めします。

    再生をリクエスト:

    curl -X GET \
     -H 'Authorization: Bearer {JWT}' \
     https://edge-auth.api.brightcove.com/playback/v1/accounts/{your_account_id}/videos/{your_video_id}
    

    ページの最終更新日05 Oct 2021