- Organized 252 files across project - Root directory: 187 → 2 files (98.9% reduction) - Moved configuration guides to docs/04-configuration/ - Moved troubleshooting guides to docs/09-troubleshooting/ - Moved quick start guides to docs/01-getting-started/ - Moved reports to reports/ directory - Archived temporary files - Generated comprehensive reports and documentation - Created maintenance scripts and guides All files organized according to established standards.
293 lines
7.0 KiB
Markdown
293 lines
7.0 KiB
Markdown
# 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`<br>`rpc-ws-prv.d-bis.org` | ✅ JWT Required | 192.168.11.251 |
|
|
| 2502 | Public RPC | `rpc-http-pub.d-bis.org`<br>`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 <token>` 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 <token>" 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
|
|
|