Hi @irvinebroque
Here is a code example for Node. I have not tested your code example for Cloudflare Worker in a browser, but it is definitely not easily translated into Node. Hence the following example for Node works, but I think you could provide a more simple approach in a future version.
- First, you need 2 string values: “keyId” and “pem”. You can store them safely, so you don’t have execute this method for every token generation
// One-time method to obtain keyId and pem for use in generateSignedToken()
// Informed by https://community.cloudflare.com/t/generating-signed-tokens-in-node/328114/3
import axios, { AxiosError, AxiosRequestConfig } from 'axios'
const jwkToPem = require('jwk-to-pem')
const obtainKeyIdAndPemForTokenGeneration = (async (params: {
cloudflareAccountId: string
cloudflareAccessToken: string
}): Promise<{ keyId: string, pem: string }> => {
const { cloudflareAccountId, cloudflareAccessToken } = params
// First, Obtain keys from Cloudflare
const obtainKeyConfig: AxiosRequestConfig<unknown> = {
method: 'post',
url: `https://api.cloudflare.com/client/v4/accounts/${ cloudflareAccountId }/stream/keys`,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${ cloudflareAccessToken }`
}
}
try {
const obtainKeyResponse = await axios(obtainKeyConfig)
const key: { id: string, pem: string, jwk: string, created: string } = obtainKeyResponse.data?.result
// Decode JWK from base64
const jwkDecoded = JSON.parse(Buffer.from(key.jwk, 'base64').toString('latin1'))
// construct pem
const pem = jwkToPem(jwkDecoded, { private: true })
// Return keyId and constructed pem
return {
keyId: key.id,
pem
}
} catch (error: unknown) {
const streamError = (error as AxiosError).response
console.log({
message: 'Error obtaining keys from Cloudflare Stream',
error: streamError || error
})
}
})
Save the keyId and pem, so you can use them for generating tokens…
- Now, when you want to generate a token, use this method:
// Use obtainKeyIdAndPemForTokenGeneration() to get pem and keyId
// Informed by https://community.cloudflare.com/t/generating-signed-tokens-in-node/328114/3
const jwt = require('jsonwebtoken')
const generateSignedToken = (async (params: {
videoId: string,
includeDownloadLink: boolean
pem: string
keyId: string
}): Promise<{
allowsDownload: boolean,
expires: number,
signedToken: string
}> => {
const { videoId, includeDownloadLink, pem, keyId } = params
const expiresTimeInSeconds = (2 * 60 * 60) // limit token lifetime to the next 2 hours
// const encoder = new TextEncoder()
const expiresIn = Math.floor(Date.now() / 1000) + expiresTimeInSeconds
const data = {
'sub': videoId,
'kid': keyId,
'exp': expiresIn,
/* 'accessRules': [
{
'type': 'ip.geoip.country',
'action': 'allow',
'country': [
'GB'
]
},
{
'type': 'any',
'action': 'block'
}
] */
}
const signedToken = jwt.sign(data, pem, { header: { 'kid': keyId }, algorithm: 'RS256' })
return {
allowsDownload: includeDownloadLink,
expires: expiresIn,
signedToken
}
})
````