Skip to main content

How to Implement JSON Web Tokens (JWT) Authorization with QuickNode

Updated on
Dec 11, 2023

9 min read

Overview

Security is a crucial factor when it comes to protecting web resources. One way to protect those resources is by integrating JSON Web Tokens (JWT) in your web applications. JWT is an open standard that defines a compact way for securely transmitting information between parties. In this guide, you will learn about the core concepts behind JWTs and how to enable JWT on your blockchain node with QuickNode. We will demonstrate this process by creating a React app that will fetch a JWT from our backend server (Express.js) and then use it to request and display the blockchain data on our front-end. 

Prerequisites:

  •  An Ethereum endpoint powered by QuickNode (create a free account here)
  •  Node.js installed
  •  A Terminal Window
  • Basic knowledge of React 
  • Basic knowledge of Express.js
DependencyVersion
node.js^18.16.0
react^18.2.0
express^4.18.2
jsonwebtoken^9.0.0

What is a JWT?

The idea behind JSON Web Tokens (JWT), also referred to as JOT is to create a standard and secure way for two parties to communicate. JWTs can be beneficial because they allow for stateless session management (no session cookies) where a backend server does not need to communicate with an authorization server. JWTs can be sent through an URL, POST parameter, or inside an HTTP header. They are also efficient due to their size. A JWT is composed of three components: A Header, Payload, and Signature. Each part is separated by a period (".") and is derived from a JSON object which is then encoded via BASE64 into a text string. All the components put together are represented in the following format:

header.payload.signature

The RFC-7519 has more details on how this standard is defined. To understand each component in-depth and understand how to decode a JWT, visit JWT.io.

These components combined are what make up a JWT. An example of a JWT would look something like this:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2Njk0Mzg4MDAsImlhdCI6MTY0ODgzNjY3Mn0.N4aNN5cwnYcMeZHeElrYtWcLxjfR-PqqLAvZNdCTGa-5wD_O3yFIM3F4ACX7egGXMCdob7UQwytMcMoAtnpKs8wyzdOlJgWyJIg3NsIWYdjnzuLz_EqNvIPdm3TEi7m0mZbgXLOGRQ_JS1RAF2i3XKPmhQuXq_ObSryPFfsLITimXJyoi5fiyX7WkUwJELIQVAlW5M5Um1fqIK791g52lIfM9vTU_PKIEJaMaBfUJMx92M04Mt8kYBjj7Eh1rxbEWeFA545HF_QKJe3j4EKoAx6BhL6oPCmoPoZXIAYlgAX6kf-FcbFfJ76u1ppeWsC0z_tfM5eDpVxHr2GY9d0o-A

JWT with QuickNode

Users can now use the JWT authentication method to protect their blockchain nodes. QuickNode supports JWT stand-alone, or it can be integrated with our other security methods such as authorization tokens, referral whitelisting, and domain masking. However, note that if multiple authentication services are enabled on a blockchain node, each method must pass its security check, or the user request will return an error.

QuickNode supports JWTs created from key pairs using the RS256 or ECDSA256 algorithm. There are no limits to how many JWTs you can activate on a blockchain node at once. Now we’re ready to create our React app!

Building a React app with JWT

Our app will be created using Express.js for the backend, which will create a REST API that will serve JWT tokens through a specific endpoint. Our front-end will fetch this JWT and then use it to make a request to our blockchain node. The following steps will show you how to create the required files in your terminal window but feel free to use a code editor such as VScode.

Open a terminal window in the directory you'd like to create the project in and run the following command:

npx create-react-app jwt-app && cd jwt-app

Once our React app is initialized, let's install the required dependencies for this JWT implementation:

npm i express jsonwebtoken 

Then we'll create the required files, one for our backend server in Express.js, and another for our key pair generation.

touch index.js && touch generateKeys.js

We'll also need to configure the package.json file to include a proxy field. The proxy field will allow for a gateway between our React app and our backend server running on Express.js. Include the following field in your package.json file: 

"proxy": "http://localhost:3001"

Next, in your terminal window run the command nano generateKeys.js to open the file (or use a code editor like VSCode). Then include the one of the following code snippets below (e.g., the RSA256 JavaScript or ES256 JavaScript example):


// Imported dependencies
const fs = require('fs')
const { generateKeyPairSync } = require('crypto');
var jwt = require('jsonwebtoken');

// Generate RSA keys
const { publicKey, privateKey } = generateKeyPairSync('rsa', {
modulusLength: 2048,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
}
});

// Write key pairs to file
fs.writeFileSync('private_key.pem', privateKey);
console.log('Saved private_key.pem');

fs.writeFileSync('public_key.pem', publicKey);
console.log('Saved public_key.pem');

Save the file by pressing CTRL + X, then click Enter on your keyboard. Once the file is saved, we’ll run the command node generateKeys.js to create a key pair (public_key.pem and private_key.pem) and store it in the same directory. Note, this file should only be ran once or you will generate new key pairs each time the file is executed.

The next step is to create our server code. Run the command nano index.js and input the following code:

// Import libraries
const express = require("express");
const fs = require("fs")
const jwt = require("jsonwebtoken")

// Server code
const PORT = process.env.PORT || 3001;
const app = express();


app.get('/get_token', (req, res) => { // endpoint to retrieve JWT

// read private key
const privateKey = fs.readFileSync(__dirname + "/private_key.pem")

// Create payload and JWT
var token = jwt.sign({}, privateKey, {

algorithm: 'RS256', // algo used to create JWT, change to ES256 if necessary
expiresIn: "2d" // set a 2 day expiration

});

return res.json({ token: token }); // return an object containing the signed JWT

})

app.listen(PORT, () => {
console.log(`Server listening on ${PORT}`); // listen to connections on the specified host and port
});

NOTE: If you used RSA256 to generate a public/private key pair in the previous step, you don't have to change anything. However, if you used ES256 to generate a public and private key pair, change the value above in the algorithm field to ES256.

Remember to save the file! Our backend code is finished, now onto initializing our frontend code.

Open the App.js file located within the src directory and input the code below. Also, remember to replace the string - "YOUR_QUICKNODE_HTTP ENDPOINT" with your actual QuickNode Endpoint. If you don't have an endpoint already, you can sign up for a free QuickNode account here and easily set up an endpoint!

import React from "react";
import "./App.css";

function App() {
const [data, setData] = React.useState(null);

React.useEffect(() => {
fetch("/get_token")
.then((res) => res.json())
.then((token) => {

fetch("YOUR_QUICKNODE_HTTP_ENDPOINT", { // don't have one? go to quicknode.com and create one now!
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': `Bearer ${token.token}`
},
body: JSON.stringify({ method: "eth_blockNumber", params: [], id: 1, jsonrpc: "2.0" })
}).then(res => res.json()).then(content => {
console.log(content)
setData(parseInt(content.result))
});

});
})

return (
<div className="App">
<header className="App-header">
<p>{!data ? "Loading..." : data}</p>
</header>
</div>
);
}

export default App;

We're almost done! Before we can start our app, we’ll need to add our public key pair to our blockchain node. Let’s quickly setup JWT authentication on QuickNode.

Add Public Key to QuickNode Node

Create a QuickNode endpoint on the Ethereum Mainnet, and navigate to your Node's Security tab, and click the Add button under the JSON Web Token.

QuickNode Security Tab

To enable JWT authorization, enter a name for your JWT, then paste the public key previously generated in your directory into the second field, titled "Public Key".

JWT Section - QuickNode Endpoints

Note, the format of the public key should look like this:

Once added, the name, ID, and fingerprint of the public key will be displayed in the JWT section within the Security tab.

JWT Added to Node Security

Starting the React App

Now that we have enabled JWT on our node, we can start our React app to create the JWT and make requests to the blockchain. First, you'll need to open two terminal windows so we can run the backend server and React app simultaneously. 

To start the backend server, run the command node index.js in your one of your terminal windows. If the server is running, you should see the following output: "Server listening on 3001"

Then in the other terminal window run the command npm start to start the React app. A browser window should automatically open to the port the app is running on and you should see a result similar to:

React App Displaying Latest Block number

If you want to dive deeper, check out this awesome GitHub repository that shows you how to implement Cloudflare workers with JWT authorization on QuickNode.

Below are some answers to common questions a user might have when using JWT on QuickNode. If you have any further questions regarding this feature or any others, please don't hesitate to reach out to us!

Questions You May Have

Q: Which chains are JWT supported on?
A: JWT is supported on all chains

Q: How do I discard a JWT before it expires?
A: If your JWT might have been exposed and you want to prevent it from being used, you can remove the public key from the Node's security tab.

Q: Can I add multiple JWTs to a blockchain node?
A: There are no limits to how many JWTs you can activate on a blockchain node at once. If multiple JWTs are active, the request should only match one of the available keys to succeed.

Q: Which cipher does QuickNode support?
A: RSA 256 (RS256) and ECDSA 256 (ES256), as specified in RFC7518 table 3.1, are only supported at this time.

Q: How do I resolve 401 errors?
A: You may have other forms of security methods enabled on your blockchain node. Check to ensure your requests meet all security checks.

Q: What expiration date should I choose?  A: You can set any expiration date in the future you'd like. Generally, the shorter the expiration time, the more secure your JWT is.

Conclusion

Congratulations on completing this guide! We've learned about JWTs and how to enable it on your blockchain node with QuickNode. Subscribe to our newsletter for more articles and guides on Ethereum. If you have any feedback, feel free to reach out to us via Twitter. You can always chat with us on our Discord community server, featuring some of the coolest developers you'll ever meet 😃

We ❤️ Feedback!

Let us know if you have any feedback or requests for new topics. We'd love to hear from you.

Share this guide