Reputation: 2408
TL:DR: replace jsonwebtoken
with jwt-decode
I have had some trouble with upgrading my existing react app to the latest version. Every time I do I get the following errors
Can't resolve 'buffer' in '/home/user/projects/trash/tokentest/test/node_modules/buffer-equal-constant-time'
Can't resolve 'stream' in '/home/user/projects/trash/tokentest/test/node_modules/buffer-equal-constant-time'
Can't resolve 'util' in '/home/user/projects/trash/tokentest/test/node_modules/buffer-equal-constant-time'
Can't resolve 'crypto' in '/home/user/projects/trash/tokentest/test/node_modules/buffer-equal-constant-time'
I can get rid of all these except crypto by installing the buffer
stream
and util
packages.
I tried installing crypto
, crypto-browserify
and crypto-js
.
I did figure out I could make it work by removing jsonwebtoken
from the project. But its not fully functional anymore after that, since its needed for user authentication.
For testing I created a completely fresh create-react-app project. It works out of the box. But as soon as I install and import jsonwebtoken
, I get the exact same errors again. Meaning even on a completely clean project, jsonwebtoken
cannot be used.
Is there a way to fix this? Because I would like to upgrade my project and use jsonwebtoken.
Upvotes: 7
Views: 15690
Reputation: 21
this is the class I have created to mock as jwt.
import * as jose from "jose";
import { convertToMilliseconds } from "../Helper/convertToMillisecond";
const SECRET = process.env.REACT_APP_PUBLIC_KEY;
const JWT_EXPIRY = convertToMilliseconds(process.env.JWT_EXPIRY || "24h");
class Jwt {
async generateToken(payload) {
try {
const secret = new TextEncoder().encode(SECRET);
const jwt = await new jose.SignJWT(payload)
.setProtectedHeader({ alg: "HS256" })
.setExpirationTime(new Date().getTime() + parseInt(JWT_EXPIRY))
.sign(secret);
return jwt;
} catch (error) {
throw error;
}
}
async generateTokenWithExpiry(payload, expiry) {
try {
const expiryInMilliseconds = convertToMilliseconds(expiry);
const secret = new TextEncoder().encode(SECRET);
const jwt = await new jose.SignJWT(payload)
.setProtectedHeader({ alg: "HS256" })
.setExpirationTime(
new Date().getTime() + parseInt(expiryInMilliseconds)
)
.sign(secret);
return jwt;
} catch (error) {
throw error;
}
}
async generateTokenWithExpiryAndNewSecret(payload, expiry, newSecret) {
try {
const secret = new TextEncoder().encode(newSecret);
const jwt = await new jose.SignJWT(payload)
.setProtectedHeader({ alg: "HS256" })
.setExpirationTime(new Date().getTime() + expiry)
.sign(secret);
return jwt;
} catch (error) {
throw error;
}
}
async decodeToken(token) {
try {
const jwt = jose.decodeJwt(token);
return jwt;
} catch (error) {
throw error;
}
}
async verifyToken(token) {
try {
const secret = new TextEncoder().encode(SECRET);
return await jose.jwtVerify(token, secret);
} catch (error) {
throw error;
}
}
}
export default new Jwt();
File ->../Helper/convertToMillisecond
export const convertToMilliseconds = (expiry) => {
const expiryValue = parseInt(expiry.substring(0, expiry.length - 1));
const expiryUnit = expiry.substring(expiry.length - 1);
let expiryInMilliseconds = 0;
switch (expiryUnit) {
case "y":
expiryInMilliseconds = expiryValue * 365 * 24 * 60 * 60 * 1000;
break;
case "w":
expiryInMilliseconds = expiryValue * 7 * 24 * 60 * 60 * 1000;
break;
case "d":
expiryInMilliseconds = expiryValue * 24 * 60 * 60 * 1000;
break;
case "h":
expiryInMilliseconds = expiryValue * 60 * 60 * 1000;
break;
case "m":
expiryInMilliseconds = expiryValue * 60 * 1000;
break;
case "s":
expiryInMilliseconds = expiryValue * 1000;
break;
default:
expiryInMilliseconds = expiryValue;
break;
}
return expiryInMilliseconds;
};
Upvotes: 2
Reputation: 11
jsonwebtoken is a Node.js module, its previous use in a React application was based on a polyfill of standard Node.js modules. Most likely a) you are relying on slow js crypto that is no longer maintained and has no feature parity with Node's crypto and b) you have significantly increased your js package size. A React update could be a webpack update, which no longer uses the dubious encryption polyfill by default.
use jose instead of jsonwebtocken https://jwt.io/libraries?language=Node.js
Upvotes: 1
Reputation: 1980
Yes. Latest React
Version is not supporting jsonwebtoken
library. Use react-jwt
library in react side to decode token
Library Link: https://www.npmjs.com/package/react-jwt
Upvotes: 1
Reputation:
jsonwebtoken
is a Node.js module, your previous use of it in a react application relied upon a polyfill of the Node.js std modules. This most likely a) relied on slow js cryptography that isn't maintained anymore and lacks feature parity with Node's crypto and b) increased your js bundle size considerably. Updating react likely meant updating webpack which no longer defaults to using the questionable crypto polyfill.
It is better to rely on modules made for either browsers or "universal", you can discover such modules amongst the ones listed on jwt.io under "JavaScript". Out of the ones listed there, jose uses purely available Web APIs.
Upvotes: 13