Skip to content

Commit

Permalink
Replace jsonwebtoken with jose
Browse files Browse the repository at this point in the history
We received a report of this package failing with the following error:

> TypeError: Right-hand side of 'instanceof' is not an object

The stack trace pointed at the jsonwebtoken package as the source.

At first it looked like this may be a problem on older versions of Node,
but it turned out that they were using a relatively recent version
(v18.17.1).

It appears that a lot of other people may be running into a similar
issue:

- auth0/node-jsonwebtoken#939
- auth0/node-jsonwebtoken#892

People have reported success by either downgrading jsonwebtoken to v8 or
replacing it with jose. Since we updated to jsonwebtoken v9 to fix a
security vulnerability, I don't think it is a great idea to go back to
v8.

jose seems to be well-supported, healthy, and active:

https://snyk.io/advisor/npm-package/jose

Let's give this a shot!

The API is a little bit different than jsonwebtoken, but for the most
part I think the new version is simple enough to transition to. I set
the alg properity to HS256, since it is required to specify the alg and
that is what jsonwebtoken uses as the default.

It seems that jose uses `||=` syntax which is not supported on node 14,
so I am also removing the node 14 tests as part of this commit.
  • Loading branch information
lencioni committed Jun 18, 2024
1 parent 1ff4154 commit ae63426
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 67 deletions.
12 changes: 0 additions & 12 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,6 @@ jobs:
- run: yarn lint
- run: yarn test

node14:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Test using Node.js 14.x
uses: actions/setup-node@v2
with:
node-version: 14.x
- run: yarn install --frozen-lockfile --ignore-engines
- run: yarn add --dev webpack@4 babel-loader@8
- run: yarn test

node18:
runs-on: ubuntu-latest
steps:
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@
"form-data": "^4.0.0",
"glob": "^7.1.2",
"https-proxy-agent": "^5.0.0",
"jose": "^5.4.1",
"jsdom": "^16.4.0",
"jsonwebtoken": "^9.0.0",
"lcs-image-diff": "^2.0.0",
"node-fetch": "^2.6.6",
"parse-srcset": "^1.0.2",
Expand Down
19 changes: 14 additions & 5 deletions src/fetchPng.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,40 @@
import { PNG } from 'pngjs';
import fetch from 'node-fetch';

import jwt from 'jsonwebtoken';
import { SignJWT } from 'jose';

export default async function fetchPng(url, { apiKey, apiSecret, endpoint }) {
const headers = {};

if (url.startsWith(endpoint)) {
headers.Authorization = `Bearer ${jwt.sign({ key: apiKey }, apiSecret, {
header: { kid: apiKey },
})}`;
const encodedSecret = new TextEncoder().encode(apiSecret);
// https://github.com/panva/jose/blob/main/docs/classes/jwt_sign.SignJWT.md
const signed = await new SignJWT({ key: apiKey })
.setProtectedHeader({ alg: 'HS256', kid: apiKey })
.sign(encodedSecret);

headers.Authorization = `Bearer ${signed}`;
}

const response = await fetch(url, {
headers,
});

if (!response.ok) {
throw new Error(
`Failed to fetch PNG at ${url}. Response ${
response.status
}: ${await response.text()}`,
);
}

const contentType = response.headers.get('Content-Type') || 'unknown';

if (!url.startsWith(endpoint) && !contentType.startsWith('image/png')) {
throw new Error(
`Failed to fetch PNG at ${url}. Response has wrong content type: ${contentType}`,
);
}

return new Promise((resolve, reject) => {
response.body
.pipe(new PNG())
Expand Down
10 changes: 6 additions & 4 deletions src/makeRequest.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import FormData from 'form-data';
import HttpsProxyAgent from 'https-proxy-agent';
import asyncRetry from 'async-retry';
import fetch from 'node-fetch';
import jwt from 'jsonwebtoken';
import { SignJWT } from 'jose';

import { version } from '../package.json';

Expand Down Expand Up @@ -52,9 +52,11 @@ export default async function makeRequest(
? JSON.stringify(jsonBody)
: undefined;

const signed = jwt.sign({ key: apiKey }, apiSecret, {
header: { kid: apiKey },
});
const encodedSecret = new TextEncoder().encode(apiSecret);
// https://github.com/panva/jose/blob/main/docs/classes/jwt_sign.SignJWT.md
const signed = await new SignJWT({ key: apiKey })
.setProtectedHeader({ alg: 'HS256', kid: apiKey })
.sign(encodedSecret);

const headers = {
Authorization: `Bearer ${signed}`,
Expand Down
70 changes: 25 additions & 45 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2164,11 +2164,6 @@ buffer-crc32@^0.2.1, buffer-crc32@^0.2.13, buffer-crc32@~0.2.3:
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==

buffer-equal-constant-time@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==

buffer-from@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
Expand Down Expand Up @@ -2581,13 +2576,6 @@ domexception@^2.0.1:
dependencies:
webidl-conversions "^5.0.0"

ecdsa-sig-formatter@1.0.11:
version "1.0.11"
resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf"
integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==
dependencies:
safe-buffer "^5.0.1"

ecstatic@^3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/ecstatic/-/ecstatic-3.3.2.tgz#6d1dd49814d00594682c652adb66076a69d46c48"
Expand Down Expand Up @@ -4065,6 +4053,11 @@ jest@^27.4.5:
import-local "^3.0.2"
jest-cli "^27.5.1"

jose@^5.4.1:
version "5.4.1"
resolved "https://registry.yarnpkg.com/jose/-/jose-5.4.1.tgz#b471ee3963920ba5452fd1b1398c8ba72a7b2fcf"
integrity sha512-U6QajmpV/nhL9SyfAewo000fkiRQ+Yd2H0lBxJJ9apjpOgkOcBQJWOrMo917lxLptdS/n/o/xPzMkXhF46K8hQ==

"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
Expand Down Expand Up @@ -4163,16 +4156,6 @@ json5@^2.1.2, json5@^2.2.1:
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.2.tgz#64471c5bdcc564c18f7c1d4df2e2297f2457c5ab"
integrity sha512-46Tk9JiOL2z7ytNQWFLpj99RZkVgeHf87yGQKsIkaPz1qSH9UczKH1rO7K3wgRselo0tYMUNfecYpm/p1vC7tQ==

jsonwebtoken@^9.0.0:
version "9.0.0"
resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz#d0faf9ba1cc3a56255fe49c0961a67e520c1926d"
integrity sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==
dependencies:
jws "^3.2.2"
lodash "^4.17.21"
ms "^2.1.1"
semver "^7.3.8"

"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.2:
version "3.3.3"
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz#76b3e6e6cece5c69d49a5792c3d01bd1a0cdc7ea"
Expand All @@ -4181,23 +4164,6 @@ jsonwebtoken@^9.0.0:
array-includes "^3.1.5"
object.assign "^4.1.3"

jwa@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a"
integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==
dependencies:
buffer-equal-constant-time "1.0.1"
ecdsa-sig-formatter "1.0.11"
safe-buffer "^5.0.1"

jws@^3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304"
integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==
dependencies:
jwa "^1.4.1"
safe-buffer "^5.0.1"

kleur@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
Expand Down Expand Up @@ -4298,7 +4264,7 @@ lodash.union@^4.6.0:
resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88"
integrity sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==

lodash@^4.17.14, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.3.0, lodash@^4.7.0:
lodash@^4.17.14, lodash@^4.17.4, lodash@^4.3.0, lodash@^4.7.0:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
Expand All @@ -4325,6 +4291,13 @@ lru-cache@^5.1.1:
dependencies:
yallist "^3.0.2"

lru-cache@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
dependencies:
yallist "^4.0.0"

make-dir@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
Expand Down Expand Up @@ -5059,7 +5032,7 @@ rx-lite@*, rx-lite@^4.0.8:
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444"
integrity sha512-Cun9QucwK6MIrp3mry/Y7hqD1oFqTYLQ4pGxaHTjIdaFDWRGGLikqp6u8LcWJnzpoALg9hap+JGk8sFIUuEGNA==

safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0:
safe-buffer@5.2.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
Expand Down Expand Up @@ -5132,10 +5105,12 @@ semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==

semver@^7.3.2, semver@^7.3.8:
version "7.6.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13"
integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==
semver@^7.3.2:
version "7.3.8"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798"
integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==
dependencies:
lru-cache "^6.0.0"

serialize-javascript@^6.0.0:
version "6.0.0"
Expand Down Expand Up @@ -5876,6 +5851,11 @@ yallist@^3.0.2:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==

yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==

yargs-parser@^20.2.2:
version "20.2.9"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
Expand Down

0 comments on commit ae63426

Please sign in to comment.