box/box-typescript-sdk-gen

Migrate from jsonwebtoken to jose to support Vercel environment

Closed this issue · 13 comments

Description of the Issue

I'm seeing the following error when trying to authenticate with JWT:

Cannot find module 'jsonwebtoken'

This happens when trying to load jsonwebtoken here. I tried adding installing jsonwebtoken to my package.json file, but the error remained.

My application is a Next.js app using the app router, uses bun install to install dependencies, and has "type": "module" in package.json. It seems like this could be a CJS vs ESM issue.

This issue has existed since v0.1.8 of box-typescript-sdk-gen.

Versions Used

Typescript SDK: v0.3.0
Platform: Node.js
Node.js: 20.11.0

Hi @michaelhays

As we decided, the JWT Authentication method is not support in browser environments by the security reason, and the jsonwebtoken is also not compatible with browsers.

The browser check should be handle from this point. So maybe the isBrowser function is missing some check with your environments, so it isn't throwing the exception.

We will check again this issue.
Bests,
Minh

Thanks @congminh1254, though this error is actually happening server-side, not in the browser.

Hello @michaelhays, thanks for posting an issue!

Using Node.js v20.11.0 and Bun v1.0.26 I create a very simple project:

package.json

{
  "name": "t2est-app",
  "version": "1.0.0",
  "description": "",
  "type": "module",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

index.js

import { BoxJwtAuth, JwtConfig } from "box-typescript-sdk-gen";

const auth = new BoxJwtAuth({
  config: new JwtConfig({
    clientId: "YOUR_CLIENT_ID",
    clientSecret: "YOUR_CLIENT_SECRET",
    jwtKeyId: "YOUR_JWT_KEY_ID",
    privateKey: "YOUR_PRIVATE_KEY",
    privateKeyPassphrase: "PASSPHRASE",
    enterpriseId: "YOUR_ENTERPRISE_ID",
  }),
});

auth.retrieveToken();

When I added the SDK dependency using bun add box-typescript-sdk-gen, the file package.json got updated accordingly and included "box-typescript-sdk-gen": "^0.3.0" in the project dependencies. The underlying version of jsonwebtoken that got installed was 9.0.2.

When trying to run the app with both bun . and node . I got an error secretOrPrivateKey is not valid key material from node_modules/jsonwebtoken/sign.js:121:24 as expected, which means that the library was load correctly. Therefore, I wasn't able to reproduce reproduce the problems using the steps you suggested.

Can you check if the jsonwebtoken actually exists in your node_modules?

Thanks for your work trying to reproduce it @mhagmajer!

Yep, I'm seeing jsonwebtoken in my node_modules/. Here's how it shows up in my bun.lockb file:

jsonwebtoken@^9.0.0, jsonwebtoken@^9.0.2:
  version "9.0.2"
  resolved "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz"
  integrity sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==
  dependencies:
    jws "^3.2.2"
    lodash.includes "^4.3.0"
    lodash.isboolean "^3.0.3"
    lodash.isinteger "^4.0.4"
    lodash.isnumber "^3.0.3"
    lodash.isplainobject "^4.0.6"
    lodash.isstring "^4.0.1"
    lodash.once "^4.0.0"
    ms "^2.1.1"
    semver "^7.5.4"

I'm pretty sure this has to do with how the app is actually built (with Next.js, next build), or possibly deployed (on Vercel), because I'm not getting the error when developing locally using next dev.

I'll try to reproduce the same error in a small project, and will share that with you here.

Here's a project with a reproduction: https://github.com/michaelhays/box-typescript-jsonwebtoken

I actually haven't deployed it to Vercel yet, but am still getting an issue when running it locally.

page.tsx is the relevant file, which has two server actions that attempt to downscope a token, the first using https://github.com/box/box-node-sdk, and the second using https://github.com/box/box-typescript-sdk-gen.

The old library downscopes the token successfully, the but the new library errors with:

Error: Request failed, status code 400: Bad Request

{
  "error": "invalid_resource",
  "error_description": "The target resource is invalid."
}

Thanks @michaelhays, I was able to reproduce the problem and I'm checking why the new library fails when downscoping the token. However, the original problem regarding loading of the jsonwebtoken does not seem to occur anymore, does it?

It only occurs in certain environments, like deploying to Vercel. I'll work on reproducing and testing that once we've figured out why the downscoping is failing with the invalid_resource error!

@michaelhays, the reason you are getting invalid_resource error when trying to downscope the token is a small bug in you authentication code. Instead of:

    const boxJwtConfig = JwtConfig.fromConfigJsonString(process.env.BOX_CONFIG);
    const boxJwtAuth = new BoxJwtAuth({ config: boxJwtConfig });
    boxJwtAuth.asUser(process.env.BOX_APP_USER_ID);

you should do:

    const boxJwtConfig = JwtConfig.fromConfigJsonString(process.env.BOX_CONFIG);
    const boxJwtAuth = await new BoxJwtAuth({ config: boxJwtConfig }).asUser(
      process.env.BOX_APP_USER_ID
    );

Please notice that asUser method does not mutate the instance of BoxJwtAuth - it creates a new one with updated settings. This function is currently asynchronous and will be made synchronous in the next release - you can await it anyway.

Using the updated code in your project, I was able to get the token correctly using both the legacy and new SDK. Thanks for providing the sample code.

As per the original issue "Cannot find module 'jsonwebtoken'", I wasn't able to reproduce it. If come across a sample project&env settings that cause this problem, please reopen this issue and we'll be happy to dig into it.

Hey @mhagmajer, thanks so much! Right you are, I made that change and it's working as expected locally :)

I deployed to Vercel and am seeing the Cannot find module 'jsonwebtoken' error now.

Vercel is the only environment I'm seeing the error in; it's working as expected every way I've tested locally:

  1. bun dev
  2. bun run build + bun start
  3. bun vercel dev

A few things I've tried:

  1. (Commit) Adding the jsonwebtoken dependency directly
  2. (Commit) Importing the new library with createRequire to force CJS
  3. (Commit) Setting "type": "commonjs" in my package.json

If you'd like, I'm happy to help you get this deployed on Vercel yourself -- it's quite easy, only takes a couple of minutes.

(I also don't think I'm able to reopen this issue myself, so you may have to do it on your end)

Given that we have isolated the problem to the Vercel environment and based on what I found here, I'll suggest to the team migrating our TypeScript library to the jose library which has support for more environments that jsonwebtoken.

Hi @michaelhays

We have just migrate from jsonwebtoken to jose and it's working on Vercel. I will let you know when it's released.

Bests,
Minh

Hi @michaelhays

New version of TS SDK is released, please try it and let us know if it's working now.

Bests,
Minh

Nice this worked!! Just updated my test project and it's working in Vercel: https://github.com/michaelhays/box-typescript-jsonwebtoken

Thanks so much team! :)