Back to Blog
Security
December 28, 2024
7 min read

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:

  • Failed authentication attempts
  • Token expiration patterns
  • Usage by user/role
  • Suspicious activity alerts
  • 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:

  • User-level access control
  • Dynamic rate limiting
  • Enhanced security
  • Detailed usage analytics

Ready to add JWT authentication to your Conduit Links? Get started now →

Share this article

View all articles

Ready to Secure Your APIs?

Join thousands of developers who trust Conduit Link to protect their API keys and build secure applications.

Connect Securely. Ship Faster.

© 2025 Conduit Link. All rights reserved.