# JWT Authentication for Permissioned RPC Endpoints **Last Updated:** 2025-12-24 **Status:** Active Configuration --- ## Overview JWT (JSON Web Token) authentication has been configured for the Permissioned RPC endpoints to provide secure, token-based access control. ### Endpoints with JWT Authentication - **HTTP RPC**: `https://rpc-http-prv.d-bis.org` - **WebSocket RPC**: `wss://rpc-ws-prv.d-bis.org` ### Endpoints without Authentication (Public) - **HTTP RPC**: `https://rpc-http-pub.d-bis.org` - **WebSocket RPC**: `wss://rpc-ws-pub.d-bis.org` --- ## Architecture ### VMID Mappings | VMID | Type | Domain | Authentication | IP | |------|------|--------|----------------|-----| | 2501 | Permissioned RPC | `rpc-http-prv.d-bis.org`
`rpc-ws-prv.d-bis.org` | ✅ JWT Required | 192.168.11.251 | | 2502 | Public RPC | `rpc-http-pub.d-bis.org`
`rpc-ws-pub.d-bis.org` | ❌ No Auth | 192.168.11.252 | ### Request Flow with JWT 1. **Client** makes request to `https://rpc-http-prv.d-bis.org` 2. **Nginx** receives request and extracts JWT token from `Authorization: Bearer ` header 3. **Lua Script** validates JWT token using secret key 4. **If valid**: Request is proxied to Besu RPC (127.0.0.1:8545) 5. **If invalid**: Returns 401 Unauthorized with error message --- ## Setup ### 1. Configure JWT Authentication Run the configuration script: ```bash cd /home/intlc/projects/proxmox ./scripts/configure-nginx-jwt-auth.sh ``` This script will: - Install required packages (nginx, lua, lua-resty-jwt) - Generate JWT secret key - Configure Nginx with JWT validation - Set up both HTTP and WebSocket endpoints ### 2. Generate JWT Tokens Use the token generation script: ```bash # Generate token with default settings (username: rpc-user, expiry: 365 days) ./scripts/generate-jwt-token.sh # Generate token with custom username and expiry ./scripts/generate-jwt-token.sh my-username 30 # 30 days expiry ``` The script will output: - The JWT token - Usage examples for testing --- ## Usage ### HTTP RPC with JWT ```bash # Test with curl curl -k \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' \ https://rpc-http-prv.d-bis.org ``` ### WebSocket RPC with JWT For WebSocket connections, include the JWT token in the Authorization header during the initial HTTP upgrade request: ```javascript // JavaScript example const ws = new WebSocket('wss://rpc-ws-prv.d-bis.org', { headers: { 'Authorization': 'Bearer YOUR_JWT_TOKEN' } }); ``` ### Using with MetaMask or dApps Most Ethereum clients don't support custom headers. For these cases, you can: 1. **Use a proxy service** that adds the JWT token 2. **Use the public endpoint** (`rpc-http-pub.d-bis.org`) for read-only operations 3. **Implement custom authentication** in your dApp --- ## Token Management ### Token Structure JWT tokens contain: - **Header**: Algorithm (HS256) and type (JWT) - **Payload**: - `sub`: Username/subject - `iat`: Issued at (timestamp) - `exp`: Expiration (timestamp) - **Signature**: HMAC-SHA256 signature using the secret key ### Token Expiry Tokens expire after the specified number of days. To generate a new token: ```bash ./scripts/generate-jwt-token.sh username days ``` ### Revoking Tokens JWT tokens cannot be revoked individually without changing the secret key. To revoke all tokens: 1. Generate a new JWT secret on VMID 2501: ```bash ssh root@192.168.11.10 "pct exec 2501 -- openssl rand -base64 32 > /etc/nginx/jwt_secret" ``` 2. Restart Nginx: ```bash ssh root@192.168.11.10 "pct exec 2501 -- systemctl restart nginx" ``` 3. Generate new tokens for authorized users --- ## Security Considerations ### Secret Key Management - **Location**: `/etc/nginx/jwt_secret` on VMID 2501 - **Permissions**: 600 (readable only by root) - **Backup**: Store securely, do not commit to version control ### Best Practices 1. **Use strong secret keys**: The script generates 32-byte random keys 2. **Set appropriate expiry**: Don't create tokens with excessive expiry times 3. **Rotate secrets periodically**: Change the secret key and regenerate tokens 4. **Monitor access logs**: Check `/var/log/nginx/rpc-http-prv-access.log` for unauthorized attempts 5. **Use HTTPS only**: All endpoints use HTTPS (port 443) ### Rate Limiting Consider adding rate limiting to prevent abuse: ```nginx limit_req_zone $binary_remote_addr zone=jwt_limit:10m rate=10r/s; location / { limit_req zone=jwt_limit burst=20 nodelay; # ... JWT validation ... } ``` --- ## Troubleshooting ### 401 Unauthorized **Error**: `{"error": "Missing Authorization header"}` **Solution**: Include the Authorization header: ```bash curl -H "Authorization: Bearer YOUR_TOKEN" ... ``` **Error**: `{"error": "Invalid or expired token"}` **Solution**: - Check token is correct (no extra spaces) - Verify token hasn't expired - Generate a new token if needed ### 500 Internal Server Error **Error**: `{"error": "Internal server error"}` **Solution**: - Check JWT secret exists: `pct exec 2501 -- cat /etc/nginx/jwt_secret` - Check lua-resty-jwt is installed: `pct exec 2501 -- ls /usr/share/lua/5.1/resty/jwt.lua` - Check Nginx error logs: `pct exec 2501 -- tail -f /var/log/nginx/rpc-http-prv-error.log` ### Token Validation Fails 1. **Verify secret key matches**: ```bash # On VMID 2501 cat /etc/nginx/jwt_secret ``` 2. **Regenerate token** using the same secret: ```bash ./scripts/generate-jwt-token.sh ``` 3. **Check token format**: Should be three parts separated by dots: `header.payload.signature` --- ## Testing ### Test JWT Authentication ```bash # 1. Generate a token TOKEN=$(./scripts/generate-jwt-token.sh test-user 365 | grep -A 1 "Token:" | tail -1) # 2. Test HTTP endpoint curl -k \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' \ https://rpc-http-prv.d-bis.org # 3. Test without token (should fail) curl -k \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' \ https://rpc-http-prv.d-bis.org # Expected: {"error": "Missing Authorization header"} ``` ### Test Health Endpoint (No Auth Required) ```bash curl -k https://rpc-http-prv.d-bis.org/health # Expected: healthy ``` --- ## Related Documentation - [RPC_DNS_CONFIGURATION.md](RPC_DNS_CONFIGURATION.md) - DNS setup - [BESU_RPC_CONFIGURATION_FIXED.md](../05-network/BESU_RPC_CONFIGURATION_FIXED.md) - Besu RPC configuration - [NGINX_ARCHITECTURE_RPC.md](../05-network/NGINX_ARCHITECTURE_RPC.md) - Nginx architecture --- ## Quick Reference **Generate Token:** ```bash ./scripts/generate-jwt-token.sh [username] [days] ``` **Use Token:** ```bash curl -H "Authorization: Bearer " https://rpc-http-prv.d-bis.org ``` **Check Secret:** ```bash ssh root@192.168.11.10 "pct exec 2501 -- cat /etc/nginx/jwt_secret" ``` **View Logs:** ```bash ssh root@192.168.11.10 "pct exec 2501 -- tail -f /var/log/nginx/rpc-http-prv-access.log" ``` --- **Last Updated**: 2025-12-24