Support Kontaktieren Sie Support | Systemstatus Systemstatus
Inhalt der Seite

    Erstellen eines JSON Web Token (JWT)

    In diesem Thema erfahren Sie, wie Sie eine JSON Web Token (JWT) erstellen, die bei der Kommunikation mit der Brightcove Playback API verwendet werden kann.

    Einführung

    Um einen zusätzlichen Schutz beim Zugriff auf Ihre Videothek hinzuzufügen oder Einschränkungen auf Benutzerebene für Ihre Inhalte anzuwenden, können Sie mit Ihrem Aufruf eine JSON Web Token (JWT) an die Brightcove Playback-API weiterleiten. Gehen Sie folgendermaßen vor, um das Token zu erstellen:

    1. Generieren eines öffentlich-privaten Schlüsselpaars
    2. Registrieren Sie den öffentlichen Schlüssel bei Brightcove
    3. Erstellen Sie ein JSON Web Token
    4. Test-Wiedergabe

    Generieren eines öffentlich-privaten Schlüsselpaars

    Der Publisher generiert ein öffentlich-privates Schlüsselpaar und stellt Brightcove den öffentlichen Schlüssel zur Verfügung. Der private Schlüssel wird vom Publisher verwendet, um Token zu signieren, und wird nicht mit Brightcove geteilt.

    Es gibt viele Möglichkeiten, das öffentlich-private Schlüsselpaar zu generieren. Hier sind ein paar Beispiele:

    Beispiel Bash-Skript:

    Beispielskript zum Generieren des Schlüsselpaars:

    #!/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"
    

    Führen Sie das Skript aus:

    $ bash keygen.sh
    
    Beispiel mit Go

    Beispiel mit der Go Programmiersprache zum Generieren des Schlüsselpaars:

    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)
      }
      
    Beispiel mit node.js

    Beispiel mit node.js zum Generieren des Schlüsselpaars:

    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");

    Registrieren öffentlicher Schlüssel

    Sie werden die Key-API verwenden, um Ihren öffentlichen Schlüssel bei Brightcove zu registrieren.

    Schlüssel-API

    Die Key-API wird verwendet, um Ihre öffentlichen Schlüssel mit Brightcove zu verwalten.

    Basis-URL

    Die Basis-URL für die API lautet:

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

    Konto-Pfad

    In allen Fällen werden Anfragen für ein bestimmtes Video Cloud-Konto gestellt. Daher fügen Sie immer den Begriff Konten gefolgt von Ihrer Konto-ID zur Basis-URL hinzu:

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

    Autorisierung

    Ein Zugriffstoken für Anfragen ist erforderlich und muss im Authorization-Header vorhanden sein:

    Authorization: Bearer {access_token}

    Das Zugriffstoken ist ein temporäres OAuth2-Zugriffstoken, das vom Brightcove OAuth Service bezogen werden muss. Weitere Informationen zum Abrufen von Client-Anmeldeinformationen und zum Abrufen von Zugriffstoken finden Sie in der Brightcove OAuth Overview.

    Berechtigungen

    Anfragen an die Schlüssel-API müssen von Client-Anmeldeinformationen mit den folgenden Berechtigungen gestellt werden:

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

    Schlüssel verwalten

    Die Key-API unterstützt die folgenden Anfragen:

    Registriere einen neuen Schlüssel:

    Geben Sie den Wert Ihres öffentlichen Schlüssels in den API-Anforderungskörper ein. Sie finden den Schlüssel in der Datei public_key.txt .

    Anforderung
    POST /v1/accounts/{accountID}/keys
        Content-Type: application/json
        Body: {"value": "MFkwEwYHKoZIzj0CAQYIKoZIzj...MyeQviqploA=="}
    
    Verwenden von Curl
    curl -X POST
      -H „Content-Type: Anwendung/JSON“\
      -H „Autorisierung: Träger {access_token}“\
      -d '{"value“: „{your_public_key_value}"}'\
    https://playback-auth.api.brightcove.com/v1/accounts/{accountID}/keys
    
    REAKTION
    {
      "id": "{your_public_key_id}",
      "type": "public",
      "algorithm": "rsa",
      "value": "{your_public_key_value}",
      "createdAt": "2020-01-03T20:30:36.488Z"
    }

    Schlüssel auflisten:

    Holen Sie sich eine Liste mit öffentlichen Schlüsseln in Ihrem Konto.

    GET /v1/accounts/{accountID}/keys

    Holen Sie sich einen Schlüssel:

    Holen Sie sich die Details für einen öffentlichen Schlüssel in Ihrem Konto.

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

    Löschen Sie einen Schlüssel:

    Löschen Sie einen öffentlichen Schlüssel in Ihrem Konto.

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

    Erstellen Sie ein JSON Web Token

    Verlage erstellen ein JSON Web Token (JWT). Das Token ist mit dem RSA-Algorithmus unter Verwendung des SHA-256-Hash-Algorithmus signiert (in der JWT-Spezifikation als "RS256„identifiziert) Es werden keine anderen JWT-Algorithmen unterstützt.

    Eine Teilmenge des Standards JSON Web Token claims wird zusammen mit einigen privaten Ansprüchen verwendet, die von Brightcove definiert wurden. Sie erstellen einen mit Ihrem privaten Schlüssel JSON Web Token signierten Schlüssel.

    Ansprüche wegen statischer URL-Lieferung

    Die folgenden Ansprüche können mit der statischen URL-Lieferung von Brightcove verwendet werden.

    Feld Art Erforderlich Beschreibung
    accid String Die Konto-ID, der der abgespielte Inhalt gehört
    drules String[] Eine Liste der anzuwendenden Aktions-IDs für Bereitstellungsregeln, siehe Implementierungsregeln für Lieferregeln . Wenn der Abfrageparameter config_id ebenfalls festgelegt ist, wird er ignoriert, da dieser Anspruch ihn außer Kraft setzt.
    exp Ganzzahl Zeit, in der dieses Token nicht mehr gültig ist, in Sekunden seit der Epoche. Muss nicht mehr als 30 Tage ab iat
    iat Ganzzahl Zeit, zu der dieses Token ausgegeben wurde, in Sekunden seit der Epoche
    conid String Falls vorhanden, autorisiert dieses Token nur das Abrufen von Lizenzen für eine bestimmte Video Cloud-Video-ID.

    Muss eine gültige Video-ID sein.
    pro String Gibt einen Schutztyp für den Fall an, dass mehrere für ein einzelnes Video verfügbar sind.

    Werte:
    • „“ (Standard für klare Inhalte)
    • „aes128"
    • „widevine“
    • „spielbereit“
    • „Fairplay“
    vod Objekt Enthält spezifische Konfigurationsoptionen für Video-On-Demand.
    ssai String Ihre serverseitige Ad Insertion (SSAI) -Konfigurations-ID. Dieser Anspruch ist erforderlich , um entweder einen HLS oder einen DASH VMAP abzurufen.

    Hier ist ein Beispiel für die JSON Web Token (JWT) Ansprüche, die Sie möglicherweise verwenden:

    {
    // 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 or reference 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"
    }
    }

    Generieren Sie ein Token

    Bibliotheken sind allgemein verfügbar, um JWT-Token zu generieren. Einzelheiten finden Sie auf der JSON Web Tokens Website.

    Beispiel Bash-Skript:

    Beispielskript zum Generieren des JWT-Token:

    #! /usr/bin/env bash
    # Static header fields.
    HEADER='{
    	"type": "JWT",
    	"alg": "RS256"
    }'
    
    payload='{
    	"pkid": "{your_public_key_id}",
    	"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"
    

    Führen Sie das Skript aus:

    $ bash jwtgen.sh
    

    Beispiel mit Go

    Hier ist ein Beispiel für eine Go Referenzimplementierung (als CLI-Tool) zum Generieren von Token ohne Verwendung einer Bibliothek von Drittanbietern:

    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)
    }
    

    Ergebnisse

    Hier ist ein Beispiel für ein dekodiertes Token mit https://JWT.io , das den vollständigen Satz von Ansprüchen angibt:

    ÜBERSCHRIFT:

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

    NUTZLAST:

    {
      "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"
    }
    

    Test-Wiedergabe

    Obwohl dies nicht erforderlich ist, möchten Sie möglicherweise die Videowiedergabe testen, bevor Sie einen Player konfigurieren.

    Wiedergabe anfragen:

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

    Seite zuletzt aktualisiert am 07. März 2020