Adding JWT Authentication to Your Conduit Links
Enhance security with JWT verification. Learn how to implement symmetric and asymmetric JWT authentication.
Conduit Link Team
Technical Content Writers
Adding JWT Authentication to Your Conduit Links
JSON Web Tokens (JWT) provide a powerful way to add authentication and authorization to your API proxies. With Conduit Link's built-in JWT verification, you can ensure that only authenticated users can access your protected APIs.
Why JWT Authentication Matters
When proxying sensitive APIs, you need more than just hiding your API key. JWT authentication adds:
- User-level access control: Different permissions for different users
- Rate limiting by user: Prevent individual users from abusing your API quotas
- Audit trails: Track who's using your APIs and when
- Token expiration: Automatic access revocation after a set time
Understanding JWT Verification in Conduit Link
Conduit Link supports both symmetric (HS256) and asymmetric (RS256) JWT verification:
Symmetric Key Verification (HS256)
Best for applications where you control both the token generation and verification:
// Server-side: Generate JWT with shared secret
const jwt = require('jsonwebtoken');const token = jwt.sign(
{
sub: userId,
email: userEmail,
role: 'premium',
exp: Math.floor(Date.now() / 1000) + (60 * 60) // 1 hour
},
process.env.JWT_SECRET,
{ algorithm: 'HS256' }
);
// Configure Conduit Link with the same secret
Asymmetric Key Verification (RS256)
Ideal for third-party authentication providers like Auth0 or Firebase Auth:
// Client receives JWT from auth provider
const token = await getTokenFromAuth0();// Conduit Link verifies with public key
const response = await fetch('https://proxy.conduit.link/YOUR-LINK-ID/api/data', {
headers: {
'Authorization': Bearer ${token}
}
});
Step-by-Step Implementation
1. Configure JWT in Conduit Link Dashboard
Navigate to your conduit link settings and enable JWT verification:
Edit your conduit link in the dashboard
Go to the "Security" tab
Enable "JWT Verification"
Choose verification type:
- Symmetric (HS256): Enter your shared secret
- Asymmetric (RS256/ES256): Enter your JWKS URL
Optional: Configure validation settings:
- Audience: Expected 'aud' claim value
- Issuer: Expected 'iss' claim value
Save your changes
2. Generate JWTs for Your Users
For a Node.js backend:
const generateUserToken = (user) => {
const payload = {
sub: user.id,
email: user.email,
role: user.subscriptionTier,
// Add any custom claims your application needs
tier: user.subscriptionTier,
permissions: user.permissions
}; return jwt.sign(payload, process.env.JWT_SECRET, {
algorithm: 'HS256',
expiresIn: '24h',
issuer: 'your-app-name'
});
};
3. Use JWTs in Client Requests
React example with automatic token refresh:
import { useAuth } from './auth-context';function useConduitAPI() {
const { getToken } = useAuth();
const fetchWithAuth = async (path, options = {}) => {
const token = await getToken(); // Handles refresh if needed
const response = await fetch(https://proxy.conduit.link/YOUR-LINK-ID${path}
, {
...options,
headers: {
...options.headers,
'X-Access-Token': 'YOUR_CONDUIT_ACCESS_TOKEN', // Required
'Authorization': Bearer ${token}
, // Your JWT for user verification
'Content-Type': 'application/json'
}
});
if (response.status === 401) {
// Token expired, refresh and retry
const newToken = await refreshToken();
return fetchWithAuth(path, options);
}
return response;
};
return { fetchWithAuth };
}
Advanced JWT Features
Per-User Rate Limiting with JWT
When JWT verification is enabled, Conduit Link automatically uses the JWT's 'sub' (subject) claim for per-user rate limiting:
const token = jwt.sign({
sub: userId, // This is used for per-user rate limiting
// Standard claims
iat: Math.floor(Date.now() / 1000),
exp: Math.floor(Date.now() / 1000) + (60 * 60),
// Your application's custom claims
email: user.email,
role: user.role,
tier: user.subscriptionTier
}, secret);
JWT with Path Variables
Conduit Link supports dynamic path restrictions using JWT claims:
// Configure allowed paths in dashboard with JWT variables
// Example allowed path: /api/users/{jwt.sub}/*const token = jwt.sign({
sub: user.id, // Will be used in path restriction
email: user.email,
role: user.role
}, secret);
// This user can only access their own data
// ✅ Allowed: /api/users/123/profile (if jwt.sub = "123")
// ❌ Denied: /api/users/456/profile
Implementing Role-Based Access in Your Backend
While Conduit Link handles JWT verification, you can implement additional access control in your application:
// Your backend validates roles from JWT
app.get('/api/admin/*', async (req, res, next) => {
const token = req.headers.authorization?.split(' ')[1];
const decoded = jwt.verify(token, secret);
if (decoded.role !== 'admin') {
return res.status(403).json({ error: 'Admin access required' });
}
next();
});
Security Best Practices
1. Token Expiration and Refresh
Always set reasonable expiration times:
// Short-lived access tokens (15 minutes)
const accessToken = jwt.sign(payload, secret, { expiresIn: '15m' });// Longer-lived refresh tokens (7 days)
const refreshToken = jwt.sign(
{ sub: userId, type: 'refresh' },
refreshSecret,
{ expiresIn: '7d' }
);
2. Secure Token Storage
Never store JWTs in localStorage. Use httpOnly cookies or memory:
// Secure cookie storage (server-side)
res.cookie('jwt', token, {
httpOnly: true,
secure: true, // HTTPS only
sameSite: 'strict',
maxAge: 3600000 // 1 hour
});// Or use memory storage with refresh mechanism
class TokenManager {
constructor() {
this.token = null;
this.refreshTimer = null;
}
setToken(token, expiresIn) {
this.token = token;
// Refresh 1 minute before expiry
const refreshIn = (expiresIn - 60) * 1000;
this.refreshTimer = setTimeout(() => this.refresh(), refreshIn);
}
async refresh() {
const newToken = await refreshAccessToken();
this.setToken(newToken.token, newToken.expiresIn);
}
}
3. Validate Everything
When configuring JWT verification in Conduit Link:
// In your Conduit Link dashboard settings:
// 1. Enable JWT Verification
// 2. Choose algorithm (HS256 for symmetric, RS256 for asymmetric)
// 3. Provide secret key or JWKS URL
// 4. Optional: Set audience and issuer validation// Ensure your JWTs include required claims
const token = jwt.sign({
sub: user.id, // Required for per-user rate limiting
exp: expiresAt, // Required for expiration validation
iat: issuedAt, // Recommended for security
iss: 'your-app', // Optional: issuer claim
aud: 'conduit-api' // Optional: audience claim
}, secret);
Monitoring and Debugging
Track JWT Usage
Monitor authentication patterns in your Conduit Link dashboard:
Debug Common Issues
// Add debug headers to identify issues
const debugRequest = async (path) => {
const response = await fetch(https://proxy.conduit.link/YOUR-LINK-ID${path}
, {
headers: {
'Authorization': Bearer ${token}
,
'X-Debug-JWT': 'true' // Returns detailed error info
}
}); if (!response.ok) {
const error = await response.json();
console.error('JWT Error:', error.jwt_error);
// Common errors:
// - "Token expired"
// - "Invalid signature"
// - "Missing required claim: email"
}
};
Integration Examples
Next.js with NextAuth
// pages/api/proxy/[...path].js
import { getToken } from 'next-auth/jwt';export default async function handler(req, res) {
const token = await getToken({ req });
if (!token) {
return res.status(401).json({ error: 'Not authenticated' });
}
// Create JWT for Conduit Link
const conduitToken = jwt.sign({
sub: token.sub,
email: token.email,
role: token.role
}, process.env.CONDUIT_JWT_SECRET);
// Proxy request
const response = await fetch(
https://proxy.conduit.link/YOUR-LINK-ID/${req.query.path.join('/')}
,
{
method: req.method,
headers: {
'Authorization': Bearer ${conduitToken}
,
'Content-Type': 'application/json'
},
body: req.method !== 'GET' ? JSON.stringify(req.body) : undefined
}
);
const data = await response.json();
res.status(response.status).json(data);
}
React Native with Secure Storage
import * as SecureStore from 'expo-secure-store';class ConduitClient {
async makeRequest(endpoint, options = {}) {
let token = await SecureStore.getItemAsync('jwt_token');
// Check if token needs refresh
if (this.isTokenExpired(token)) {
token = await this.refreshToken();
}
const response = await fetch(
https://proxy.conduit.link/YOUR-LINK-ID${endpoint}
,
{
...options,
headers: {
...options.headers,
'Authorization': Bearer ${token}
}
}
);
return response;
}
isTokenExpired(token) {
const decoded = jwt.decode(token);
return decoded.exp < Date.now() / 1000;
}
}
Conclusion
JWT authentication transforms your Conduit Links from simple API proxies into sophisticated, secure gateways. By implementing proper JWT verification, you gain:
Ready to add JWT authentication to your Conduit Links? Get started now →
Ready to Secure Your APIs?
Join thousands of developers who trust Conduit Link to protect their API keys and build secure applications.