Build more with QuickNode - New pricing plans and a free tier! Read the press release

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

May 03, 2022

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 Node powered by QuickNode 
  •  Node.js installed
  •  A Terminal Window
  • Basic knowledge of React 
  • Basic knowledge of Express.js

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

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. Then include the following code:

building a react app with jwt

Copy
// 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 by file by pressing CTRL + X then 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:

building a react app with jwt

Copy
//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
    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
});

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 trial here!
 

building a react app with jwt

Copy
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:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3T6lKe23ssMpRWmT12z+
4MdAyO/Qea5yLe29jSw8S8rvtvhMC3pfY83tRCqe5AjA0sr6q5nzoD7h+7FV+Fd1
t70zztlyDG5ErXPHotmhpi9jnyOmaAB8a3i66ZtJE9qIP+Deo8YcnyuN2KXKeSG/
p6mglkPQZM0kCqVs8/w5Wa6HPXtu1NzlhxMwj3kS1pnuIIPsi7I9C2nyA4TbRWwE
7MEc5kqIKqBnAlybaWxmD8BDK9w7Ac0hmdivUAhTl69Aov11CgRzvCyyh53OkKAa
BUKlqTesg2a5jP/pg1bL+l8fcmLOeQOUgq1VyUPfXyBsdxISpvhQrW/AA8906YqS
jwIDAQAB
-----END PUBLIC KEY-----

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 (EC256), 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 😃

Related articles 21

How to setup WebHooks with QuickNode
Apr 12, 2022

In this article, we'll learn about WebHooks and how we can set-up WebHooks with QuickNode.What are WebHooks?Everything we do on the internet can be marked/considered as events and as the internet grows, these events grow in...

Continue reading
How to set a custom provider in MetaMask
Apr 12, 2022

MetaMask is one of the essential tools for web3 development. It comes set up with Ethereum blockchain networks out of the box. But there can be some specific use cases where you might want to add a custom provider to MetaMask for faster transaction processing or to...

Continue reading
How to Set Up Multi-Token Authentication on QuickNode
Jun 20, 2022

Security is an important part of developing a resilient Web3 application. If the security of your blockchain infrastructure is compromised, it can lead to downtime for your users. We here at QuickNode recently released a new update to our security features available on...

Continue reading
How to setup referrer whitelist with QuickNode
Apr 12, 2022

Security is one of the most significant aspects when developing an application. If a resource like a node falls into the hands of an unauthorized individual, it can exhaust your limits and resources. In this guide, we will see how to avoid this and learn how to set up a...

Continue reading
An Introduction to the Solana Account Model
Apr 20, 2022

The Solana account model is a critical part of the Solana ecosystem and can be one the hardest concepts for developers, especially ones transitioning from other blockchains, to understand. To work on the Solana blockchain efficiently, a...

Continue reading
Web3 Glossary
Jul 28, 2022

Your guide to navigating the lingo of Web3. If you have any feedback or would like to submit a suggestion to this glossary, kindly let us know in this form.

Continue reading
Pending and Queued Transactions Explained
Apr 12, 2022

The Ethereum network processes over one million transactions a day. These transactions originate from users wanting to transfer Ether or interact with smart contracts. In this guide, we will teach you about the Pending and Queued state of transactions on the Ethereum...

Continue reading
What are Ethereum Transactions?
Apr 12, 2022

Transactions in Ethereum are cryptographically signed data messages that contain a set of instructions. These instructions can interpret to sending Ether from one Ethereum account to another or interacting with a smart contract deployed on the blockchain. Transactions are...

Continue reading
Blockchain Consensus Mechanisms
May 31, 2022

Data consistency and security are the principles that guide blockchain technology. There are different mechanisms and algorithms blockchains use to regulate their working throughout the chain to achieve this. In this guide, we will learn about the various blockchain...

Continue reading