Skip to main content

How to Protect Your Endpoint - Front End Best Practices

Created on
Updated on
Nov 26, 2024

9 min read

Overview​

If you are building a front-end decentralized application (dApp), your site will need to connect to the chain with an endpoint node. You can think of your endpoint as an API key that allows you to connect to the chain. If you are using a front-end (e.g., a Candy Machine Mint Page or a Defi Application), you may be exposing your endpoint to the public. This means a malicious actor could exploit and use your private endpoint. This could run up your bill and cause other performance issues. In this guide, you will learn various strategies to protect your endpoint when using a front end:

TacticEase/ComplexityEffectivenessQuickNode Plan
Rotate Keys🟑 Moderate🟒 HighAll plans
Dot Env with Backend Proxy🟒 Easyβšͺ Moderaten/a
Rate Limiting🟒 Easyβšͺ ModerateAll plans
Domain Whitelisting🟑 Moderateβšͺ ModerateAll plans
JSON Web Tokens (JWT)πŸ”΄ Complex🟒 HighAll plans
Endpoint Armor🟑 Moderate🟒 HighMarketplace Add-on

Rotate Keys​

Rotating your keys is a simple yet effective method for protecting your endpoint. It involves regularly rotating your endpoint's private token to prevent unauthorized access. This means that even if your endpoint is exposed, it will only be vulnerable for a limited time. QuickNode allows you to rotate your keys directly from your QuickNode dashboard.

Just open your QuickNode Dashboard (https://dashboard.quicknode.com/) and select the endpoint you want to rotate keys for. Click the Security Tab and scroll to the "Authentication: Tokens" section. Here, you can add or delete new keys. New keys will be available immediately. Just copy the new key and use it in your application. You can delete old keys by clicking the πŸ—‘οΈ button next to the key you want to remove. Any previously compromised keys that have been removed are no longer valid.

Regularly rotating your keys can significantly reduce the risk of unauthorized access to your endpoint. For more information on how to rotate your keys, check out our Guide: How to Set Up Multi-Token Authentication on QuickNode.


Rotate Keys Pros and Cons
  • Pros: Simple, Secure
  • Cons: Time-consuming (requires regular key rotation), Key Management

Dot Env and Backend Proxy​

Dot Env​

Dot Env (.env) is a simple yet effective method for managing environment variables in your application. It involves using a .env file to store configuration settings and sensitive information, such as API keys and database passwords. This approach centralizes configuration management, making it easier to update and maintain. Dot Env has several benefits:

  1. Security: Keeps sensitive data out of your codebase, reducing the risk of exposing it in version control systems.
  2. Flexibility: Allows different configurations for different environments (e.g., development, testing, production) without changing the code.
  3. Ease of Use: Simplifies managing environment-specific variables.

Backend Proxy​

While Dot Env is effective for managing environment variables, variables stored in .env files can be inadvertently exposed if the file is served to the client side. A backend proxy serves as an excellent solution to this problem. A backend proxy is a middleman between the client and server sides. It can handle requests requiring sensitive data, like your endpoint, without exposing them to the client. Here's an example of a backend proxy making a Solana getBalance request:

backendProxy.js
const dotenv = require('dotenv');
dotenv.config();
const PRIVATE_ENDPOINT = process.env.PRIVATE_ENDPOINT;
const solanaWeb3 = require('@solana/web3.js');
const app = express();

app.get('/getBalance', async (req, res) => {
const connection = new solanaWeb3.Connection(
PRIVATE_ENDPOINT,
'confirmed',
);
const balance = await connection.getBalance(req.query.publicKey);
res.send(balance);
});

This approach has several benefits:


  1. Secure Data Handling: The backend proxy can securely handle requests and manage sensitive data, like API keys, without exposing them to the client side.
  2. Environment Variables: Store sensitive data in .env on the server and use the backend proxy to mediate interactions with external services.
  3. Reduced Exposure Risk: This approach significantly reduces the risk of sensitive information exposure, as the data never reaches the front end.

Best Practices​


  • Use Dot Env Server-Side: Store sensitive variables in .env server files, not client-side code.
  • Do not Commit .env Files: Ensure .env files are not committed to public repositories (use .gitignore).
  • Implement Backend Proxy: Use a backend proxy to handle requests that require sensitive data, ensuring this data is not exposed in the client-side application.

By combining Dot Env with a backend proxy, you can maintain the ease and security of environment variable management while safeguarding against the risks of client-side exposure.


Dot Env and Backend Proxy Pros and Cons
  • Pros: Adaptable, Scalable, Secure
  • Cons: Codebase Complexity (additional server-side code) and Performance Overhead

Rate Limiting​

Rate limiting is crucial to endpoint security, especially in web applications and APIs. It involves setting a maximum number of requests your endpoint can handle within a given time frame. Though this will not prevent others from accessing your endpoint, it will limit the number of requests they can make. This can help prevent abuse and overuse of resources, which can lead to performance issues and increased costs.

Setting Rate Limits​

QuickNode lets you set rate limits for any endpoints directly from your QuickNode dashboard. Go to your QuickNode Dashboard (https://dashboard.quicknode.com/) and select the endpoint you want to apply rate limits to. Click the Security Tab and scroll to the "Rate Limits" section. Here, you can apply limits to your endpoint regarding Requests per Second, Minute, or Day.

Select the rate limit type you want to apply, enter the limit, and click Add. Your rate limits will be applied immediately.


Method Rate Limits​

QuickNode also offers method-specific rate limits. These can be found on the same endpoint security page in the dashboard. Method rate limits allow you to set different limits for different API methods, providing more granular control over your endpoint's usage.

Rate Limiting Pros and Cons
  • Pros: Easy to implement/modify
  • Cons: Could impact user experience if limits are too low, Does not prevent access to endpoint

Domain Whitelisting​

Domain whitelisting (or referrer whitelisting) is a simple yet effective method for restricting access to your endpoint. It involves creating a list of approved domains that can access your endpoint. This can help prevent unauthorized access and abuse of your endpoint. QuickNode allows you to whitelist multiple referrers for any of your endpoints directly from your QuickNode dashboard.

Whitelisting Domains​

Go to your QuickNode Dashboard (https://dashboard.quicknode.com/) and select the endpoint you want to apply whitelists to. Click the Security Tab and scroll down to the "Referrer Whitelist" section. Here, you can add domains to your whitelist. Enter the domain you want to whitelist and click Add. Your whitelist will be applied immediately. You can easily delete a whitelisted domain by clicking the πŸ—‘οΈ button next to the domain you want to remove.

After it's saved, you can test your whitelist by making a request to your endpoint with a cURL script or from a domain that is not whitelisted. You should receive an UNAUTHORIZED response.

For example, this request:

curl https://your-endpoint.solana-mainnet.quiknode.pro/123/ \
-X POST \
-H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","id":1, "method":"getBlock"}'

Should now return:

{ 
"error":"UNAUTHORIZED",
"instance":"your-endpoint",
"request-id":""
}

Domain Whitelisting Pros and Cons
  • Pros: Easy to implement/modify
  • Cons: Limited effectiveness

For more information on how to whitelist domains, check out our Guide: How to setup referrer whitelist with QuickNode.

JSON Web Tokens (JWT)​

JSON Web Tokens (JWT) are a popular method for securing APIs. They are an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA. JWTs are commonly used for authentication and information exchange in web applications and APIs.

JWTs prevent unauthorized access by verifying the integrity of the information contained within the token. This is accomplished by signing a duration-limited token with a secret or a public/private key pair. Requests received without a token or with an invalid token (either because it has expired or was not signed with the correct secret) will be rejected.

Implementing JWTs​

Here's a simple example of how to implement JWTs in your application (for a more detailed walkthrough, check out our Guide: How to Implement JWT Authorization with QuickNode):


  1. Key Generation: Generate a public/private key pair using RSA or ECDSA. Example:
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',
}
});

  1. Define Key: Add your public key to your QuickNode dashboard (Security Tab).
  2. Token Generation: In your backend, generate a limited duration JWT using your private key (e.g., 60 seconds for handling a transaction request). Example:
const app = express();
const jwt = require("jsonwebtoken");

app.get('/get_token', (req, res) => { // endpoint to retrieve JWT
const privateKey = process.env;
var token = jwt.sign({}, privateKey, {
algorithm: 'RS256', // RSA signature with SHA-256
expiresIn: "60000" // 30 seconds
});
return res.json({ token: token }); // return an object containing the signed JWT
});

  1. Establish Connection: In your front-end, connect to your endpoint using the JWT. Example:
const { Connection } = require('@solana/web3.js');
async function makeRequest() {
const token = await fetch('/get_token'); // fetch JWT from backend
const connection = new Connection('https://example.solana-devnet.quiknode.pro/12345/', {
httpHeaders: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': `Bearer ${token.token}`
}
});
const block = await connection.getBlock();
// do something with the block
}
makeRequest();

  1. Token Verification: When we receive the request, we can verify the token using the public key you added to your QuickNode dashboard. This will ensure the token is valid and has not been tampered with.

Best Practices​


  • Key Management: Securely manage and regularly rotate cryptographic keys.
  • Token Expiration: Set appropriate token expiration times to reduce the risk of token misuse.
JSON Web Tokens (JWT)
  • Pros: Secure, Scalable, Adaptable
  • Cons: Codebase Complexity (additional server-side code and key management)

Endpoint Armor​

Endpoint Armor is a powerful add-on that provides an additional layer of security for your endpoint. Think of Endpoint Armor as an advanced rate limiter and firewall that can be configured to block requests based on a variety of factors, including:


  • global limits,
  • visitor limits,
  • method-specific limits,
  • method restrictions,
  • parameter restrictions,
  • contract restrictions

Using Endpoint Armor​

Endpoint Armor is an add-on available through the QuickNode Marketplace. To add Endpoint Armor to your endpoint, go to your QuickNode Dashboard (https://dashboard.quicknode.com/) and select the endpoint you want to add Endpoint Armor to. Click the Add-ons Tab and scroll down to the "Endpoint Armor" section. Click Install. Your Endpoint Armor will be applied to your account immediately.

To use your Armor, you will need to do two things:

  1. Update your endpoint URL (Endpoint Armor uses a unique subdomain: demo-endpoint.quiknode.pro -> demo-endpoint.secure.quiknode.pro)
  2. Define your Armor Rules. Here's an example implementation:
{
"methods": {
"getSlot": {
"reqPerHour": 1000,
"reqPerMinute": 100,
"reqPerSecond": 10,
"minBlockNumber": 24000000
}
},
"visitorRateLimits": {
"reqPerMinute": 10
}
}

The above example whitelists one method: getSlot. It will allow 1,000 requests per hour, 100 per minute, and 10 per second (globally). It will also only allow requests for slots above 24,000,000. Finally, it will allow ten requests per minute from a single visitor to your website.

For more details on how to deploy Endpoint Armor, check out our Guide: How to Deploy Endpoint Armor.


Endpoint Armor Pros and Cons
  • Pros: Secure, Scalable, Configurable
  • Cons: Additional Cost, Endpoint is Visible (so it can be targeted within the limits of the Armor)

Wrap Up​

Practicing good endpoint security on your front end is crucial for protecting your endpoint from unauthorized access and abuse. Implementing the strategies outlined in this guide can significantly reduce the risk of unauthorized access to your endpoint.

If you are stuck or have questions, drop them in our Discord. Stay up to date with the latest by following us on Twitter (@QuickNode) or our Telegram announcement channel.

We ❀️ Feedback!

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

Resources​

Share this guide