# WebSocket Server Authentication This document describes the optional authentication features added to the Circle WebSocket server. ## Overview The WebSocket server now supports optional secp256k1 signature-based authentication while maintaining full backward compatibility with existing clients. Authentication is completely opt-in and can be enabled per server instance. ## Features ### 1. Optional Authentication - **Backward Compatible**: Existing clients continue to work without any changes - **Opt-in**: Authentication can be enabled/disabled per server instance - **Graceful Degradation**: Servers can accept both authenticated and unauthenticated connections ### 2. Nonce-based Security - **Nonce Endpoints**: REST API for requesting cryptographic nonces - **Replay Protection**: Each nonce can only be used once - **Expiration**: Nonces expire after 5 minutes - **Health Monitoring**: Health endpoint for monitoring nonce service ### 3. Signature Verification - **secp256k1**: Uses the same cryptographic standard as Ethereum - **Ethereum-style Signing**: Compatible with eth_sign message format - **Public Key Recovery**: Verifies signatures against provided public keys ## API Endpoints These HTTP API endpoints are served by the WebSocket server instance itself, on the same host and port where the WebSocket service is running. ### Nonce Request ``` GET /auth/nonce?public_key= ``` **Response:** ```json { "nonce": "nonce_1234567890_abcdef", "expires_at": 1234567890 } ``` ### Health Check ``` GET /auth/health ``` **Response:** ```json { "status": "healthy", "active_nonces": 42, "timestamp": 1234567890 } ``` ## WebSocket Authentication ### Query Parameters Clients can authenticate by including these query parameters in the WebSocket URL: - `pubkey`: The client's public key in hex format (130 characters, uncompressed) - `sig`: The signature of the nonce in hex format (130 characters) - `nonce`: The nonce that was signed (optional) **Example:** ``` ws://localhost:8080/{circle_pk}?pubkey=04abc123...&sig=def456...&nonce=nonce_123_abc ``` ### Authentication Flow 1. **Request Nonce**: Client requests a nonce from `/auth/nonce` 2. **Sign Nonce**: Client signs the nonce with their private key 3. **Connect**: Client connects to WebSocket with `pubkey` and `sig` parameters 4. **Verify**: Server verifies the signature and accepts/rejects the connection ## Server Configuration ### Basic Server (No Authentication) ```rust use circle_ws_lib::{ServerConfig, spawn_circle_server}; let config = ServerConfig::new( "localhost".to_string(), 8080, "redis://localhost".to_string(), ); let (server_task, server_handle) = spawn_circle_server(config)?; ``` ### Server with Authentication ```rust use circle_ws_lib::{ServerConfig, spawn_circle_server}; let config = ServerConfig::new( "localhost".to_string(), 8080, "redis://localhost".to_string(), ).with_auth(); let (server_task, server_handle) = spawn_circle_server(config)?; ``` ## Client Integration ### JavaScript/TypeScript Example ```javascript // 1. Request nonce (from the WebSocket server's HTTP interface) const nonceResponse = await fetch('http://localhost:8080/auth/nonce'); const { nonce } = await nonceResponse.json(); // 2. Sign nonce (using your preferred secp256k1 library) const signature = signMessage(privateKey, nonce); const publicKey = derivePublicKey(privateKey); // 3. Connect with authentication (replace {circle_pk} with actual circle public key) const ws = new WebSocket( `ws://localhost:8080/${circle_pk}?pubkey=${publicKey}&sig=${signature}&nonce=${nonce}` ); ``` ### Rust Client Example ```rust use circle_ws_lib::auth::*; // Request nonce. NonceClient will derive the HTTP API path from this WebSocket URL. let nonce_client = NonceClient::from_ws_url("ws://localhost:8080/{circle_pk}")?; let nonce_response = nonce_client.request_nonce(Some(public_key)).await?; // Sign nonce let signature = sign_message(&private_key, &nonce_response.nonce)?; // Connect with authentication (replace {circle_pk} with actual circle public key) let ws_url = format!( "ws://localhost:8080/{}?pubkey={}&sig={}", circle_pk, public_key, signature ); ``` ## Security Considerations ### Nonce Management - Nonces expire after 5 minutes - Each nonce can only be used once - Nonces are stored in memory (consider Redis for production) ### Signature Security - Uses secp256k1 elliptic curve cryptography - Ethereum-style message signing for compatibility - Public key verification prevents impersonation ### Backward Compatibility - Unauthenticated connections are allowed by default - No breaking changes to existing APIs - Optional authentication can be enabled gradually ## Error Handling ### Authentication Errors - **401 Unauthorized**: Authentication required but not provided - **403 Forbidden**: Authentication provided but invalid - **400 Bad Request**: Malformed authentication parameters ### Nonce Errors - **404 Not Found**: Nonce endpoint not available - **410 Gone**: Nonce expired or already used - **429 Too Many Requests**: Rate limiting (if implemented) ## Monitoring ### Metrics - Active nonce count via `/auth/health` - Authentication success/failure rates in logs - Connection counts by authentication status ### Logging ``` INFO Incoming WebSocket connection for circle: 04abc123... (auth_enabled: true) INFO Authentication successful for pubkey: 04abc123... WARN Authentication failed: invalid signature ``` ## Production Considerations ### Scalability - Consider Redis-backed nonce storage for multiple server instances - Implement rate limiting for nonce requests - Monitor memory usage of in-memory nonce storage ### Security - Use HTTPS/WSS in production - Implement proper key management - Consider certificate-based authentication for additional security ### Monitoring - Set up alerts for authentication failure rates - Monitor nonce service health - Track connection patterns and anomalies ## Migration Guide ### Existing Deployments 1. **No Changes Required**: Existing clients continue to work 2. **Gradual Rollout**: Enable authentication on new servers first 3. **Client Updates**: Update clients to support authentication when ready 4. **Full Migration**: Eventually require authentication on all servers ### Testing 1. Test unauthenticated connections still work 2. Test authenticated connections with valid signatures 3. Test authentication failures are handled gracefully 4. Test nonce expiration and replay protection