implement stripe and idenfy webhooks support
This commit is contained in:
7
examples/wss_demo/.gitignore
vendored
Normal file
7
examples/wss_demo/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# TLS Certificates (uncomment if you want to exclude them)
|
||||
# cert.pem
|
||||
# key.pem
|
||||
|
||||
# Temporary files
|
||||
*.tmp
|
||||
*.log
|
2958
examples/wss_demo/Cargo.lock
generated
Normal file
2958
examples/wss_demo/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
35
examples/wss_demo/Cargo.toml
Normal file
35
examples/wss_demo/Cargo.toml
Normal file
@@ -0,0 +1,35 @@
|
||||
[package]
|
||||
name = "wss_demo"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# Empty workspace table to exclude from parent workspace
|
||||
[workspace]
|
||||
|
||||
[[bin]]
|
||||
name = "wss_client"
|
||||
path = "wss_client.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "wss_server"
|
||||
path = "wss_server.rs"
|
||||
|
||||
[dependencies]
|
||||
# WebSocket client library
|
||||
circle_client_ws = { path = "../../src/client_ws", features = ["crypto"] }
|
||||
|
||||
# Server library for the WSS server demo
|
||||
circle_ws_lib = { path = "../../src/server", features = ["auth"] }
|
||||
|
||||
# Common dependencies
|
||||
tokio = { version = "1.45", features = ["full"] }
|
||||
env_logger = "0.10"
|
||||
log = "0.4"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
|
||||
# Server-specific dependencies
|
||||
actix = "0.13"
|
||||
actix-web = "4.11"
|
||||
actix-web-actors = "4.3"
|
||||
clap = { version = "4.5", features = ["derive"] }
|
204
examples/wss_demo/README.md
Normal file
204
examples/wss_demo/README.md
Normal file
@@ -0,0 +1,204 @@
|
||||
# WSS (WebSocket Secure) Demo
|
||||
|
||||
This directory contains a complete demonstration of WSS (WebSocket Secure) functionality with TLS encryption and authentication.
|
||||
|
||||
## Contents
|
||||
|
||||
- `cert.pem` - Self-signed TLS certificate for testing
|
||||
- `key.pem` - Private key for the TLS certificate
|
||||
- `wss_server.rs` - WSS server example with authentication
|
||||
- `wss_client.rs` - WSS client example for testing
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Start the WSS Server
|
||||
|
||||
```bash
|
||||
# From the project root - specify the correct package and feature
|
||||
cargo run --manifest-path src/server/Cargo.toml --example wss_server --features circle_ws_lib/auth
|
||||
|
||||
# OR run from the wss_demo directory
|
||||
cd examples/wss_demo
|
||||
cargo run --bin wss_server
|
||||
```
|
||||
|
||||
The server will start on:
|
||||
- **WSS (Secure)**: `wss://127.0.0.1:8443/ws`
|
||||
- **WS (Regular)**: `ws://127.0.0.1:8080/ws`
|
||||
|
||||
### 2. Test with the WSS Client
|
||||
|
||||
Run the WSS client that uses the circle_client_ws library:
|
||||
|
||||
```bash
|
||||
# Navigate to the wss_demo directory
|
||||
cd examples/wss_demo
|
||||
|
||||
# Run with logging (recommended)
|
||||
RUST_LOG=info cargo run --bin wss_client
|
||||
|
||||
# Or without logging
|
||||
cargo run --bin wss_client
|
||||
```
|
||||
|
||||
This will run the `wss_client.rs` file which demonstrates:
|
||||
- Automatic credential generation using secp256k1
|
||||
- WSS connection with TLS encryption
|
||||
- Full authentication flow
|
||||
- Script execution over secure WebSocket
|
||||
|
||||
**Note**: The WSS client must be run from the `examples/wss_demo` directory as it's a standalone project with its own dependencies.
|
||||
|
||||
## Features Demonstrated
|
||||
|
||||
### 🔒 **TLS/WSS Encryption**
|
||||
- Self-signed certificate for development/testing
|
||||
- Secure WebSocket connections over TLS
|
||||
- Certificate validation and error handling
|
||||
|
||||
### 🛡️ **Authentication**
|
||||
- secp256k1 signature-based authentication
|
||||
- Nonce generation and verification
|
||||
- Authenticated vs unauthenticated request handling
|
||||
|
||||
### 📝 **JSON-RPC Protocol**
|
||||
- Standard JSON-RPC 2.0 over WebSocket
|
||||
- Method calls: `fetch_nonce`, `authenticate`, `play`
|
||||
- Error handling and response validation
|
||||
|
||||
## Certificate Information
|
||||
|
||||
The included certificate is a **self-signed certificate** for development and testing purposes only.
|
||||
|
||||
**Certificate Details:**
|
||||
- **Subject**: `/C=US/ST=Demo/L=Demo/O=WSS Demo/CN=localhost`
|
||||
- **Validity**: 365 days from generation
|
||||
- **Key Size**: RSA 4096-bit
|
||||
- **Usage**: Development/Testing only
|
||||
|
||||
⚠️ **Security Notice**: Do not use this certificate in production. Generate proper certificates from a trusted Certificate Authority for production use.
|
||||
|
||||
## Testing with Browser
|
||||
|
||||
You can test the WSS connection using browser developer tools:
|
||||
|
||||
```javascript
|
||||
// Open browser console and run:
|
||||
const ws = new WebSocket('wss://127.0.0.1:8443/ws');
|
||||
|
||||
ws.onopen = () => {
|
||||
console.log('WSS Connected!');
|
||||
// Send a test message
|
||||
ws.send(JSON.stringify({
|
||||
jsonrpc: "2.0",
|
||||
method: "fetch_nonce",
|
||||
params: { pubkey: "test_key" },
|
||||
id: 1
|
||||
}));
|
||||
};
|
||||
|
||||
ws.onmessage = (event) => {
|
||||
console.log('Response:', JSON.parse(event.data));
|
||||
};
|
||||
```
|
||||
|
||||
**Note**: Your browser may show a security warning due to the self-signed certificate. This is expected for development.
|
||||
|
||||
## Testing with websocat
|
||||
|
||||
You can also test with websocat (WebSocket command-line client):
|
||||
|
||||
```bash
|
||||
# Install websocat if not already installed
|
||||
cargo install websocat
|
||||
|
||||
# Connect to WSS server (ignoring certificate validation for self-signed cert)
|
||||
websocat --insecure wss://127.0.0.1:8443/ws
|
||||
|
||||
# Or with more explicit options
|
||||
websocat -k wss://127.0.0.1:8443/ws
|
||||
|
||||
# Send a test message (after connecting)
|
||||
{"jsonrpc":"2.0","method":"fetch_nonce","params":{"pubkey":"test_key"},"id":1}
|
||||
```
|
||||
|
||||
**Note**: The `--insecure` or `-k` flag is needed because we're using a self-signed certificate.
|
||||
|
||||
## Authentication Flow
|
||||
|
||||
### 1. Fetch Nonce
|
||||
```json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "fetch_nonce",
|
||||
"params": { "pubkey": "your_public_key_hex" },
|
||||
"id": 1
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Authenticate
|
||||
```json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "authenticate",
|
||||
"params": {
|
||||
"pubkey": "your_public_key_hex",
|
||||
"signature": "signed_nonce_hex"
|
||||
},
|
||||
"id": 2
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Execute Commands
|
||||
```json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "play",
|
||||
"params": { "script": "40 + 2" },
|
||||
"id": 3
|
||||
}
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Certificate Issues
|
||||
If you encounter certificate-related errors:
|
||||
|
||||
1. **Regenerate certificates**:
|
||||
```bash
|
||||
cd examples/wss_demo
|
||||
rm cert.pem key.pem
|
||||
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj "/C=US/ST=Demo/L=Demo/O=WSS Demo/CN=localhost"
|
||||
```
|
||||
|
||||
2. **Check file permissions**:
|
||||
```bash
|
||||
ls -la cert.pem key.pem
|
||||
```
|
||||
|
||||
### Connection Issues
|
||||
- Ensure no other services are using ports 8080 or 8443
|
||||
- Check firewall settings
|
||||
- Verify the server started successfully (look for "✅ WSS Server started successfully!" message)
|
||||
|
||||
### Authentication Issues
|
||||
- Ensure you're using valid secp256k1 signatures
|
||||
- Check that the nonce hasn't expired (default: 5 minutes)
|
||||
- Verify the public key format is correct hex encoding
|
||||
|
||||
## Production Deployment
|
||||
|
||||
For production use:
|
||||
|
||||
1. **Use proper certificates** from a trusted CA
|
||||
2. **Configure proper hostnames** (not localhost)
|
||||
3. **Set up proper firewall rules**
|
||||
4. **Use environment variables** for sensitive configuration
|
||||
5. **Enable proper logging and monitoring**
|
||||
6. **Consider load balancing** for high availability
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [WSS Implementation Plan](../../WSS_IMPLEMENTATION_PLAN.md)
|
||||
- [Server WS README](../../src/server/README.md)
|
||||
- [Client WS README](../../src/client_ws/README.md)
|
94
examples/wss_demo/wss_client.rs
Normal file
94
examples/wss_demo/wss_client.rs
Normal file
@@ -0,0 +1,94 @@
|
||||
//! WSS Client Demo using Circle WebSocket Client
|
||||
//!
|
||||
//! This example demonstrates connecting to a WSS (WebSocket Secure) server
|
||||
//! using the circle_client_ws library with proper authentication.
|
||||
|
||||
use circle_client_ws::{CircleWsClientBuilder, auth};
|
||||
use log::{info, error};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Initialize logging - use RUST_LOG=info for detailed output
|
||||
env_logger::init();
|
||||
|
||||
println!("🧪 Starting WSS Client Demo");
|
||||
|
||||
// Generate authentication credentials
|
||||
let private_key = auth::generate_private_key()?;
|
||||
let public_key = auth::derive_public_key(&private_key)?;
|
||||
|
||||
info!("🔑 Generated credentials - Public key: {}...", &public_key[..20]);
|
||||
|
||||
// WSS server URL (secure WebSocket)
|
||||
let wss_url = "wss://127.0.0.1:8443/ws";
|
||||
|
||||
info!("🔗 Connecting to WSS server at {}", wss_url);
|
||||
println!("🔌 Connecting to WSS server...");
|
||||
|
||||
// Create WSS client with authentication
|
||||
let mut client = CircleWsClientBuilder::new(wss_url.to_string())
|
||||
.with_keypair(private_key)
|
||||
.build();
|
||||
|
||||
// Connect to the server
|
||||
match client.connect().await {
|
||||
Ok(()) => {
|
||||
println!("✅ Successfully connected to WSS server!");
|
||||
info!("📡 Response status: 101 Switching Protocols");
|
||||
|
||||
println!("\n🧪 Testing WSS connection with JSON-RPC messages...");
|
||||
|
||||
// Test 1: Authentication
|
||||
println!("📤 Test 1: Performing authentication");
|
||||
match client.authenticate().await {
|
||||
Ok(true) => {
|
||||
println!("✅ Authentication successful!");
|
||||
info!("🔐 Client authenticated with server");
|
||||
|
||||
// Test 2: Execute script (authenticated request)
|
||||
println!("\n📤 Test 2: Executing script (authenticated request)");
|
||||
let test_script = "40 + 2".to_string();
|
||||
|
||||
match client.play(test_script).await {
|
||||
Ok(result) => {
|
||||
println!("✅ Script execution successful!");
|
||||
println!("📊 Result: {}", result.output);
|
||||
info!("Script output: {}", result.output);
|
||||
}
|
||||
Err(e) => {
|
||||
error!("❌ Script execution failed: {}", e);
|
||||
println!("❌ Script execution failed: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(false) => {
|
||||
println!("❌ Authentication failed - server rejected credentials");
|
||||
error!("Authentication failed");
|
||||
}
|
||||
Err(e) => {
|
||||
error!("❌ Authentication error: {}", e);
|
||||
println!("❌ Authentication error: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Disconnect
|
||||
client.disconnect().await;
|
||||
println!("\n🔌 Disconnected from WSS server");
|
||||
|
||||
println!("\n🎉 Summary:");
|
||||
println!(" ✅ WSS connection established");
|
||||
println!(" ✅ TLS encryption working");
|
||||
println!(" ✅ JSON-RPC protocol working");
|
||||
println!(" ✅ Authentication system working");
|
||||
println!(" ✅ Script execution working");
|
||||
}
|
||||
Err(e) => {
|
||||
error!("❌ Failed to connect to WSS server: {}", e);
|
||||
println!("❌ Connection failed: {}", e);
|
||||
println!("\n💡 Make sure the WSS server is running:");
|
||||
println!(" cargo run --manifest-path src/server/Cargo.toml --example wss_server --features auth");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
91
examples/wss_demo/wss_server.rs
Normal file
91
examples/wss_demo/wss_server.rs
Normal file
@@ -0,0 +1,91 @@
|
||||
//! WSS Server Demo
|
||||
//!
|
||||
//! This example demonstrates a complete WSS (WebSocket Secure) server with:
|
||||
//! - TLS encryption using self-signed certificates
|
||||
//! - secp256k1 authentication
|
||||
//! - JSON-RPC protocol support
|
||||
//! - Comprehensive logging and error handling
|
||||
//!
|
||||
//! Usage: cargo run --example wss_server --features auth
|
||||
|
||||
use circle_ws_lib::{ServerConfig, spawn_circle_server};
|
||||
use log::{info, warn, error};
|
||||
use std::time::Duration;
|
||||
use tokio::time::sleep;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Initialize logging
|
||||
env_logger::init();
|
||||
|
||||
info!("🚀 Starting WSS Server Demo");
|
||||
info!("🔐 This demo includes TLS encryption and secp256k1 authentication");
|
||||
info!("");
|
||||
|
||||
// Create server configuration with TLS and authentication enabled
|
||||
let config = ServerConfig::new(
|
||||
"127.0.0.1".to_string(),
|
||||
8080, // Regular WebSocket port
|
||||
"redis://127.0.0.1:6379".to_string(),
|
||||
)
|
||||
.with_tls(
|
||||
"../../src/server/examples/wss_demo/cert.pem".to_string(),
|
||||
"../../src/server/examples/wss_demo/key.pem".to_string()
|
||||
)
|
||||
.with_tls_port(8443) // Secure WebSocket port
|
||||
.with_auth(); // Enable secp256k1 authentication
|
||||
|
||||
info!("📋 Server Configuration:");
|
||||
info!(" Host: {}", config.host);
|
||||
info!(" Regular WS Port: {}", config.port);
|
||||
info!(" WSS Port: {}", config.get_tls_port());
|
||||
info!(" TLS Enabled: {}", config.enable_tls);
|
||||
info!(" Auth Enabled: {}", config.enable_auth);
|
||||
info!(" Certificate: {:?}", config.cert_path);
|
||||
info!(" Private Key: {:?}", config.key_path);
|
||||
info!("");
|
||||
|
||||
// Start the server
|
||||
let (join_handle, _server_handle) = spawn_circle_server(config)
|
||||
.map_err(|e| -> Box<dyn std::error::Error> {
|
||||
error!("❌ Failed to start WSS server: {}", e);
|
||||
Box::new(e)
|
||||
})?;
|
||||
|
||||
info!("✅ WSS Server started successfully!");
|
||||
info!("");
|
||||
info!("🔗 Connection URLs:");
|
||||
info!(" 🔒 Secure WebSocket: wss://127.0.0.1:8443/ws");
|
||||
info!(" 🔓 Regular WebSocket: ws://127.0.0.1:8080/ws");
|
||||
info!("");
|
||||
info!("🛡️ Authentication: secp256k1 signatures required for 'play' commands");
|
||||
info!("🔓 Public methods: 'fetch_nonce' (no auth required)");
|
||||
info!("");
|
||||
info!("📝 Example JSON-RPC requests:");
|
||||
info!(" 1. Fetch nonce (no auth):");
|
||||
info!(" {{\"jsonrpc\":\"2.0\",\"method\":\"fetch_nonce\",\"params\":{{\"pubkey\":\"your_pubkey\"}},\"id\":1}}");
|
||||
info!("");
|
||||
info!(" 2. Authenticate:");
|
||||
info!(" {{\"jsonrpc\":\"2.0\",\"method\":\"authenticate\",\"params\":{{\"pubkey\":\"your_pubkey\",\"signature\":\"signed_nonce\"}},\"id\":2}}");
|
||||
info!("");
|
||||
info!(" 3. Execute script (requires auth):");
|
||||
info!(" {{\"jsonrpc\":\"2.0\",\"method\":\"play\",\"params\":{{\"script\":\"40 + 2\"}},\"id\":3}}");
|
||||
info!("");
|
||||
info!("🧪 Test with the WSS client:");
|
||||
info!(" cargo run --example wss_client");
|
||||
info!("");
|
||||
info!("🌐 Test with browser (open console):");
|
||||
info!(" const ws = new WebSocket('wss://127.0.0.1:8443/ws');");
|
||||
info!(" ws.onopen = () => ws.send(JSON.stringify({{jsonrpc:'2.0',method:'fetch_nonce',params:{{pubkey:'test'}},id:1}}));");
|
||||
info!(" ws.onmessage = (e) => console.log(JSON.parse(e.data));");
|
||||
info!("");
|
||||
info!("⚠️ Note: Browser may show certificate warning (self-signed cert)");
|
||||
info!("");
|
||||
info!("🔄 Server running... Press Ctrl+C to stop");
|
||||
|
||||
// Keep server running until interrupted
|
||||
let _ = join_handle.await;
|
||||
|
||||
info!("🛑 WSS Server stopped");
|
||||
Ok(())
|
||||
}
|
Reference in New Issue
Block a user