auth0 / node-jws

JSON Web Signatures
http://self-issued.info/docs/draft-ietf-jose-json-web-signature.html
MIT License
709 stars 108 forks source link

Doesn't work with esbuild/Vite.js #101

Open kitsune7 opened 3 years ago

kitsune7 commented 3 years ago

Please do not report security vulnerabilities here. The Responsible Disclosure Program details the procedure for disclosing security issues.

Thank you in advance for helping us to improve this library! Please read through the template below and answer all relevant questions. Your additional work here is greatly appreciated and will help us respond as quickly as possible. For general support or usage questions, use the Auth0 Community or Auth0 Support. Finally, to avoid duplicates, please search existing Issues before submitting one here.

By submitting an Issue to this repository, you agree to the terms within the Auth0 Code of Conduct.

Description

Provide a clear and concise description of the issue, including what you expected to happen.

I'm trying to convert a project from using Webpack to Vite.js (which uses esbuild internally for development builds), and I'm getting the following error/stack trace:

inherits_browser.js:5 Uncaught TypeError: Object prototype may only be an Object or null: undefined
    at Function.create (<anonymous>)
    at Object.inherits (inherits_browser.js:5)
    at node_modules/jws/lib/data-stream.js (data-stream.js:39)
    at __require2 (chunk-IHTDASF6.js?v=d5f5f338:17)
    at node_modules/jws/lib/sign-stream.js (sign-stream.js:3)
    at __require2 (chunk-IHTDASF6.js?v=d5f5f338:17)
    at node_modules/jws/index.js (index.js:2)
    at __require2 (chunk-IHTDASF6.js?v=d5f5f338:17)
    at node_modules/jsonwebtoken/decode.js (decode.js:1)
    at __require2 (chunk-IHTDASF6.js?v=d5f5f338:17)

I expected the library to work just as well on Vite.js as it did when using Webpack to compile.

I'm raising this issue here because I think I found a way to fix the problem by removing this package's dependency on util.inherits, the use of which is now discouraged.

Reproduction

Detail the steps taken to reproduce this error, what was expected, and whether this issue can be reproduced consistently or if it is intermittent.

Where applicable, please include:

  • Code sample to reproduce the issue
  • Log files (redact/remove sensitive information)
  • Application settings (redact/remove sensitive information)
  • Screenshots
Screen Shot 2021-08-11 at 3 21 47 PM

Relevant code samples: tldr; I'm calling the jwt.sign function.

/* I've omitted/changed much of the code here for security and relevance */
import jwt from 'jsonwebtoken';

export type userType = 'a' | 'b';
export type JwtPayload = {
  type: userType;
  ACLS: { [key: string]: CoreACLs[] };
  aud: [string];
  exp: number;
  expBuffer: number;
  iat: number;
  jti: string;
  user_id?: string;
  username?: string;
};

export type Auth = JwtPayload & {
  jwt: string;
  loading?: boolean;
  error?: string;
};

export const mockAuth = (props: Partial<Auth> = {}): Auth => {
  const now = Math.floor(Date.now() / 1000);
  const auth: Omit<Auth, 'jwt'> = {
    ACLS: {
      /* ... */
    },
    aud: ['us'],
    exp: now + 14400,
    expBuffer: now + 28800,
    iat: now - 3600,
    jti: uuid(),
    type: 'a',
    user_id: uuid(),
    username: 'testing@domain.com',
    ...props,
  };
  return {
    jwt: jwt.sign(auth, 'fakePrivateKey'),
    ...auth,
  };
};

Environment

Please provide the following:

kitsune7 commented 3 years ago

I've been tracing this issue for a bit now, but I think I found the issue. stream is a Node.js library that's not available in the browser and it's therefore undefined when we try to inherit from it.

Is this library meant to be browser compatible, or is it meant to be used strictly in Node.js?

pierre-borckmans commented 2 years ago

@kitsune7 Did you ever find a solution to this?

kitsune7 commented 2 years ago

@pierre-borckmans Unfortunately, I haven't found anything to make this repository work without Node.js-specific libraries.

I did have some luck implementing the functionality I needed in pure JavaScript with the help of a blog post I found, but I could only get that working asynchronously, which broke the flow I wanted for some things.

However, in trying to find that blog post again to link it here, I did find a repository called jsrsasign that may handle things better. I haven't tried that one yet, but it seems to support signing json web tokens in pure JavaScript synchronously.

Kuznetsov-Ilia commented 2 years ago

the cheapest way I found to "solve" this issue in vite is to mock node.js modules in vite.config.ts:

define: {
    global: {},
    stream: {},
    process: {},
 },

and to fake "inherits" module and do the check there

{
resolve: {
    alias: {
      inherits: './inherits.js',
    },
  },
}

in inherits.js you can put an easy check.

function inherits(ctor, superCtor) {
  if (!superCtor.prototype) return
  ctor.super_ = superCtor
  ctor.prototype = Object.create(superCtor.prototype, {
    constructor: {
      value: ctor,
      enumerable: false,
      writable: true,
      configurable: true,
    },
  })
}
module.exports = inherits
FossPrime commented 2 years ago

The biggest issue for me is the dependency on the deprecated safe-buffer module. https://www.npmjs.com/package/safe-buffer#safer-nodejs-buffer-api

sduduzog commented 2 years ago

Hey all, just to drop what worked for me, if anyone is trying to use this with Nuxt 3. I was adding aliasses one by one to try see where the issue would happen next and i boiled it down to the builting "stream" module. If you try to alias with stream-browserify it breaks again when it can't get to readable-stream but the snippet below folved the issue for me

alias: {
    stream: 'readable-stream',
},

Of course you need to install readable-stream via npm/yarn

nzuyanov commented 1 year ago

I also faced this problem. My application is based on Nuxt 3 + Vite and none of the solutions suggested above helped. Then I did some research and found a plugin that solved the problem

https://www.npmjs.com/package/vite-plugin-node-polyfills

import { nodePolyfills } from 'vite-plugin-node-polyfills'

// vite.config or vite section of nuxt.config
plugins: [
    nodePolyfills({
      protocolImports: true,
    }),
],
arnaldoperez commented 1 year ago

@nzuyanov your solution is excellent, straightforward, and clean. It totally worked on Nuxt3 for me to this day. But it is still concerning that this issue has been open for so long without any official answer...

netanel-mce commented 9 months ago

So does anyone have a solution for esbuild? maybe @evanw?