Files
proxmox/docs/04-configuration/RPC_JWT_SETUP_COMPLETE.md
defiQUG fbda1b4beb
Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
docs: Ledger Live integration, contract deploy learnings, NEXT_STEPS updates
- ADD_CHAIN138_TO_LEDGER_LIVE: Ledger form done; public code review repo bis-innovations/LedgerLive; init/push commands
- CONTRACT_DEPLOYMENT_RUNBOOK: Chain 138 gas price 1 gwei, 36-addr check, TransactionMirror workaround
- CONTRACT_*: AddressMapper, MirrorManager deployed 2026-02-12; 36-address on-chain check
- NEXT_STEPS_FOR_YOU: Ledger done; steps completable now (no LAN); run-completable-tasks-from-anywhere
- MASTER_INDEX, OPERATOR_OPTIONAL, SMART_CONTRACTS_INVENTORY_SIMPLE: updates
- LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE: bis-innovations/LedgerLive reference

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 15:46:57 -08:00

8.5 KiB

JWT Authentication Setup - Complete

Last Updated: 2026-01-31
Document Version: 1.0
Status: Active Documentation


Date: 2025-12-26
Status: FULLY OPERATIONAL


Setup Complete

JWT authentication has been successfully configured for the Permissioned RPC endpoints on VMID 2501.

Endpoints Configured

Endpoint VMID IP Authentication Status
https://rpc-http-prv.d-bis.org 2501 192.168.11.251 JWT Required Active
wss://rpc-ws-prv.d-bis.org 2501 192.168.11.251 JWT Required Active
https://rpc-http-pub.d-bis.org 2502 192.168.11.252 No Auth Active
wss://rpc-ws-pub.d-bis.org 2502 192.168.11.252 No Auth Active

🔑 JWT Secret

Location: /etc/nginx/jwt_secret on VMID 2501
Secret: UMW58gEniB9Y75yNmw0X9hI+ycg1K+d1TG8VdB6TqX0=

⚠️ IMPORTANT: Keep this secret secure. All JWT tokens are signed with this secret.


🚀 Quick Start

1. Generate a JWT Token

cd /home/intlc/projects/proxmox
./scripts/generate-jwt-token.sh [username] [expiry_days]

Example:

./scripts/generate-jwt-token.sh my-app 30

2. Use the Token

HTTP RPC:

curl -k \
  -H "Authorization: Bearer YOUR_TOKEN_HERE" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' \
  https://rpc-http-prv.d-bis.org

WebSocket RPC:

const ws = new WebSocket('wss://rpc-ws-prv.d-bis.org', {
  headers: {
    'Authorization': 'Bearer YOUR_TOKEN_HERE'
  }
});

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

{"jsonrpc":"2.0","error":{"code":-32000,"message":"Unauthorized. Missing or invalid JWT token. Use: Authorization: Bearer <token>"},"id":null}

📋 Services Status

VMID 2501 Services

  • Nginx: Active and running
  • JWT Validator Service: Active on port 8888
  • Besu RPC: Running on ports 8545 (HTTP) and 8546 (WebSocket)

Check Status

ssh root@192.168.11.10 "pct exec 2501 -- systemctl status nginx jwt-validator"

🔧 Configuration Files

Nginx Configuration

  • Location: /etc/nginx/sites-available/rpc-perm
  • Enabled: /etc/nginx/sites-enabled/rpc-perm

JWT Validator Service

  • Script: /usr/local/bin/jwt-validator-http.py
  • Service: /etc/systemd/system/jwt-validator.service
  • Port: 8888 (internal only, 127.0.0.1)

JWT Secret

  • Location: /etc/nginx/jwt_secret
  • Permissions: 640 (readable by root and www-data group)

🧪 Testing

Test Health Endpoint (No Auth Required)

curl -k https://rpc-http-prv.d-bis.org/health
# Expected: healthy

Test with Valid Token

# Generate token
TOKEN=$(./scripts/generate-jwt-token.sh test-user 365 | grep "Token:" | tail -1 | awk '{print $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

# Expected: {"jsonrpc":"2.0","id":1,"result":"0x8a"}

Test with Invalid Token

curl -k \
  -H "Authorization: Bearer invalid-token" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' \
  https://rpc-http-prv.d-bis.org

# Expected: 401 Unauthorized

🔄 Token Management

Generate New Token

./scripts/generate-jwt-token.sh [username] [expiry_days]

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

Token Expiry

Tokens expire after the specified number of days. To generate a new token:

./scripts/generate-jwt-token.sh username days

Revoke All Tokens

To revoke all existing tokens, generate a new JWT secret:

ssh root@192.168.11.10 "pct exec 2501 -- openssl rand -base64 32 > /etc/nginx/jwt_secret"
ssh root@192.168.11.10 "pct exec 2501 -- chmod 640 /etc/nginx/jwt_secret && chgrp www-data /etc/nginx/jwt_secret"
ssh root@192.168.11.10 "pct exec 2501 -- systemctl restart jwt-validator"

Then generate new tokens for authorized users.


🌐 DNS Configuration

Required DNS Records

Ensure these DNS records are configured in Cloudflare:

Type Name Target Proxy Notes
A rpc-http-prv 192.168.11.251 🟠 Proxied Permissioned HTTP RPC
A rpc-ws-prv 192.168.11.251 🟠 Proxied Permissioned WebSocket RPC
A rpc-http-pub 192.168.11.252 🟠 Proxied Public HTTP RPC
A rpc-ws-pub 192.168.11.252 🟠 Proxied Public WebSocket RPC

Verify DNS

# Check DNS resolution
dig rpc-http-prv.d-bis.org
nslookup rpc-http-prv.d-bis.org

🔍 Troubleshooting

401 Unauthorized

Issue: Token is missing or invalid

Solutions:

  1. Check Authorization header format: Authorization: Bearer <token>
  2. Verify token hasn't expired
  3. Generate a new token
  4. Ensure token matches the current JWT secret

500 Internal Server Error

Issue: JWT validation service not responding

Solutions:

# Check service status
ssh root@192.168.11.10 "pct exec 2501 -- systemctl status jwt-validator"

# Check logs
ssh root@192.168.11.10 "pct exec 2501 -- journalctl -u jwt-validator -n 20"

# Restart service
ssh root@192.168.11.10 "pct exec 2501 -- systemctl restart jwt-validator"

Connection Refused

Issue: Service not listening on port 8888

Solutions:

# Check if service is running
ssh root@192.168.11.10 "pct exec 2501 -- ss -tlnp | grep 8888"

# Check JWT secret permissions
ssh root@192.168.11.10 "pct exec 2501 -- ls -la /etc/nginx/jwt_secret"

# Fix permissions if needed
ssh root@192.168.11.10 "pct exec 2501 -- chmod 640 /etc/nginx/jwt_secret && chgrp www-data /etc/nginx/jwt_secret"

Nginx Configuration Errors

Issue: Nginx fails to start or reload

Solutions:

# Test configuration
ssh root@192.168.11.10 "pct exec 2501 -- nginx -t"

# Check error logs
ssh root@192.168.11.10 "pct exec 2501 -- tail -20 /var/log/nginx/rpc-http-prv-error.log"

# Reload nginx
ssh root@192.168.11.10 "pct exec 2501 -- systemctl reload nginx"

📊 Monitoring

View Access Logs

# HTTP access logs
ssh root@192.168.11.10 "pct exec 2501 -- tail -f /var/log/nginx/rpc-http-prv-access.log"

# WebSocket access logs
ssh root@192.168.11.10 "pct exec 2501 -- tail -f /var/log/nginx/rpc-ws-prv-access.log"

# Error logs
ssh root@192.168.11.10 "pct exec 2501 -- tail -f /var/log/nginx/rpc-http-prv-error.log"

Monitor JWT Validator Service

ssh root@192.168.11.10 "pct exec 2501 -- journalctl -u jwt-validator -f"

🔐 Security Best Practices

  1. Keep JWT Secret Secure

    • Store in secure location
    • Don't commit to version control
    • Rotate periodically
  2. Set Appropriate Token Expiry

    • Use short expiry for high-security applications
    • Use longer expiry for trusted services
    • Regenerate tokens when compromised
  3. Monitor Access

    • Review access logs regularly
    • Watch for unauthorized access attempts
    • Set up alerts for suspicious activity
  4. Use HTTPS Only

    • All endpoints use HTTPS (port 443)
    • Never send tokens over unencrypted connections
  5. Rate Limiting (Future Enhancement)

    • Consider adding rate limiting to prevent abuse
    • Configure per-user or per-IP limits


Verification Checklist

  • JWT authentication configured on VMID 2501
  • JWT validator service running on port 8888
  • Nginx configured with auth_request
  • JWT secret generated and secured
  • Token generation script working
  • Valid tokens allow access
  • Invalid tokens are rejected
  • Health endpoint accessible without auth
  • Documentation complete

Last Updated: 2025-12-26
Status: PRODUCTION READY