Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
- 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>
360 lines
8.5 KiB
Markdown
360 lines
8.5 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
cd /home/intlc/projects/proxmox
|
|
./scripts/generate-jwt-token.sh [username] [expiry_days]
|
|
```
|
|
|
|
**Example:**
|
|
```bash
|
|
./scripts/generate-jwt-token.sh my-app 30
|
|
```
|
|
|
|
### 2. Use the Token
|
|
|
|
**HTTP RPC:**
|
|
```bash
|
|
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:**
|
|
```javascript
|
|
const ws = new WebSocket('wss://rpc-ws-prv.d-bis.org', {
|
|
headers: {
|
|
'Authorization': 'Bearer YOUR_TOKEN_HERE'
|
|
}
|
|
});
|
|
```
|
|
|
|
### 3. Test Without Token (Should Fail)
|
|
|
|
```bash
|
|
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:**
|
|
```json
|
|
{"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
|
|
|
|
```bash
|
|
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)
|
|
|
|
```bash
|
|
curl -k https://rpc-http-prv.d-bis.org/health
|
|
# Expected: healthy
|
|
```
|
|
|
|
### Test with Valid Token
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
./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:
|
|
|
|
```bash
|
|
./scripts/generate-jwt-token.sh username days
|
|
```
|
|
|
|
### Revoke All Tokens
|
|
|
|
To revoke all existing tokens, generate a new JWT secret:
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
# 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**:
|
|
```bash
|
|
# 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**:
|
|
```bash
|
|
# 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**:
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
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
|
|
|
|
---
|
|
|
|
## 📚 Related Documentation
|
|
|
|
- [RPC_JWT_AUTHENTICATION.md](RPC_JWT_AUTHENTICATION.md) - Detailed JWT authentication guide
|
|
- [RPC_DNS_CONFIGURATION.md](RPC_DNS_CONFIGURATION.md) - DNS setup and configuration
|
|
- [BESU_RPC_CONFIGURATION_FIXED.md](../05-network/BESU_RPC_CONFIGURATION_FIXED.md) - Besu RPC node configuration
|
|
|
|
---
|
|
|
|
## ✅ Verification Checklist
|
|
|
|
- [x] JWT authentication configured on VMID 2501
|
|
- [x] JWT validator service running on port 8888
|
|
- [x] Nginx configured with auth_request
|
|
- [x] JWT secret generated and secured
|
|
- [x] Token generation script working
|
|
- [x] Valid tokens allow access
|
|
- [x] Invalid tokens are rejected
|
|
- [x] Health endpoint accessible without auth
|
|
- [x] Documentation complete
|
|
|
|
---
|
|
|
|
**Last Updated**: 2025-12-26
|
|
**Status**: ✅ **PRODUCTION READY**
|
|
|