はじめに
CloudflareStreamにおける、署名付きURLのトークンを/token
エンドポイントを使わずに自前で発行する方法。
ドキュメントにはJavaScriptの例しかなかったので、Goで書き換え。
※あくまで一例なので、より適した方法もあるかもしれません。
ドキュメントでいうこの部分
また、JWK,JWSなどの前提知識については以下がわかりやすかったです。
実装
JWKの取り扱いについては、以下のライブラリを使用。
JWSの生成は、crypto/rsa
パッケージを利用して、signatureを生成しました。
そのため、JWKのjsonを一度Raw状態にしてから、rsa.PrivateKey
にキャストしています。
func streamSignedURL() (string, error) {
jwkKey := "{PRIVATE-KEY-IN-JWK-FORMAT}"
keyID := "<KEY_ID>"
videoUID := "<VIDEO_UID>"
expiresTimeInS = 3600
header := map[string]any{
"alg": "RS256",
"kid": keyID,
}
data := map[string]any{
"sub": streamId,
"kid": keyID,
"exp": time.Now().Add(time.Duration(exp) * time.Second).Unix(),
}
jwkJson, _ := base64.StdEncoding.DecodeString(jwkKey)
var raw interface{}
err = jwk.ParseRawKey(jwkJson, &raw)
if err != nil {
return "", fmt.Errorf("cloudflare streamSignedURL failed jwk.ParseRawKey err %w", err)
}
rsaKey := raw.(*rsa.PrivateKey)
token := fmt.Sprintf("%s.%s", objectToBase64url(header), objectToBase64url(data))
hash := sha256.Sum256([]byte(token))
buf, err := rsa.SignPKCS1v15(nil, rsaKey, crypto.SHA256, hash[:])
if err != nil {
return "", fmt.Errorf("cloudflare streamSignedURL failed rsa.Sign err %w", err)
}
signedToken := fmt.Sprintf("%s.%s", token, bufferToBase64Url(buf))
return signedToken, nil
}
func bufferToBase64Url(buffer []byte) string {
return base64.RawURLEncoding.EncodeToString(buffer)
}
func objectToBase64url(payload map[string]any) string {
json, _ := json.Marshal(payload)
return bufferToBase64Url(json)
}