mux-node-sdk icon indicating copy to clipboard operation
mux-node-sdk copied to clipboard

Make this work on Cloudflare workers

Open dylanjha opened this issue 3 years ago • 1 comments

The require('fs') line crashes in cloudflare workers environment.

https://github.com/muxinc/mux-node-sdk/blob/master/src/utils/jwt.js#L6

https://community.cloudflare.com/t/cant-resolve-fs-in-cloudflare-workers/112762

dylanjha avatar Aug 31 '20 15:08 dylanjha

@dylanjha I think that node based crypto (https://www.npmjs.com/package/jsonwebtoken) may not work as well.

maciektr avatar Jan 03 '22 10:01 maciektr

Just looked through the code, saw axios and was happy that it's not using http or request or sthg to then stumble upon fs 🥲 So have to use the rest api directly "again" 😅

Totally get that it was build like that, nowadays with all the different environments, Deno, Bun, V8, Workers etc it's really nice to be less Node dependent 🥰

Anyway, this is not stopping us from switching from CF Stream to Mux 🤓

CanRau avatar Jan 25 '23 22:01 CanRau

For anyone following along, there are a couple core issues here:

  • require('fs') crashes in non-node (this is probably fixable in this SDK)
  • this package takes a dependency on jsonwebtoken, which uses native node:crypto stuff, which doesn't work in CF workers (this is probably fixable in this SDK, we can use something else)
  • CF workers and some of these other node-like environments do support Web Crypto.
  • Unfortunately, Web Crypto requires pkcs8 packaged keys, by default Mux gives you pkcs1 packaged secret key
  • Mux can make some updates to give people pkcs8 keys instead to make things easier (I'll see if we can do this)
  • But short of that, it's fairly easy to convert pkcs8 keys to pkcs1 so that it is compatible with Web Crypto libs

Here's an example in TypeScript for creating a signed token in a way that's compatible with Web Crypto:

import * as jose from "jose";
let rs = require("jsrsasign");

const alg = "RS256";

export async function sign(
  privateKey: any,
  claims: any
): Promise<string> {
  const pk = atob(privateKey);

  const pcks1 = rs.KEYUTIL.getKey(pk);
  const pcks8 = rs.KEYUTIL.getPEM(pcks1, "PKCS8PRV");

  // WebCrypto needs a pcks8 with no header, footer, or newlines
  // So strip these off in the laziest way
  const cleanPcks1 = pcks8
    .replace("-----BEGIN PRIVATE KEY-----", "")
    .replace("-----END PRIVATE KEY-----", "")
    .replace(/(\r\n|\n|\r)/gm, "");

  const key = await importPrivateKey(cleanPcks1).catch((e) => {
    console.log(`Error loading key: ${e}`);
  });

  const jwt = await new jose.SignJWT(claims)
    .setProtectedHeader({ alg })
    .setExpirationTime("1d")
    // eslint-disable-next-line
    // @ts-ignore
    .sign(key);

  return jwt;
}

dylanjha avatar Feb 18 '23 00:02 dylanjha

Is there any plan to support edge runtimes?
As replacement of jsonwebtoken, jose can be used that is safe on non-node environment.

ramiel avatar Nov 06 '23 22:11 ramiel

Hi folks, version 8 (beta) is available for use and supports other runtimes.

See here for details: https://github.com/muxinc/mux-node-sdk/issues/327

dylanjha avatar Jan 12 '24 21:01 dylanjha

Version 8 is released with compatibility for alternate JS runtimes:

https://github.com/muxinc/mux-node-sdk/releases/tag/v8.0.0

dylanjha avatar Feb 12 '24 20:02 dylanjha