freezone/portal-server/README.md
2025-06-30 17:01:40 +02:00

414 lines
12 KiB
Markdown

# Portal Server
A dedicated HTTP server for the portal application that provides KYC verification endpoints and Stripe payment processing.
## Features
- **KYC Verification**: Integration with Identify API for identity verification
- Create verification sessions
- Handle verification result webhooks
- Check verification status
- **Payment Processing**: Stripe integration for company and resident registrations
- Create payment intents for companies and residents
- Handle Stripe webhooks
- Payment success/failure redirects
- **Security Features**: Production-ready security configurations
- **API Key Authentication**: Configurable API key authentication for protected endpoints
- **Webhook Signature Verification**: HMAC-SHA256 verification for Stripe and Identify webhooks
- Feature-based CORS policies (dev vs prod)
- Origin restrictions for production deployments
- **Configurable**: Command-line flags and environment variables
- **Static File Serving**: Optional static file serving
## Quick Start
> **Getting 401 errors?** See the detailed [SETUP.md](SETUP.md) guide for step-by-step instructions.
## Quick Start
### 1. Set Up Environment File
The portal-server requires API keys for authentication. Create a `.env` file to get started quickly:
```bash
# Copy the example file
cp .env.example .env
# Edit the .env file with your actual keys
nano .env
```
### 2. Configure Required Keys
Edit your `.env` file with these **required** values:
```bash
# Stripe Configuration (Required)
STRIPE_SECRET_KEY=sk_test_your_actual_stripe_secret_key
STRIPE_PUBLISHABLE_KEY=pk_test_your_actual_stripe_publishable_key
# Identify KYC Configuration (Required)
IDENTIFY_API_KEY=your_actual_identify_api_key
# API Keys for Authentication (Required to avoid 401 errors)
API_KEYS=dev_key_123,another_key_456
```
### 3. Run the Server
```bash
# Run with .env file (recommended)
cargo run -- --from-env --verbose
# Or specify custom .env file location
cargo run -- --from-env --env-file /path/to/your/.env --verbose
```
### 4. Test API Access
All protected endpoints require the `x-api-key` header:
```bash
# Test with API key (replace dev_key_123 with your actual key)
curl -X GET http://localhost:3001/api/health \
-H "x-api-key: dev_key_123"
# Without API key = 401 Unauthorized
curl -X GET http://localhost:3001/api/health
```
### 5. Common Issues
**Getting 401 Unauthorized?**
- ✅ Make sure `API_KEYS` is set in your `.env` file
- ✅ Include `x-api-key` header in all API requests
- ✅ Use one of the keys from your `API_KEYS` list
**Server won't start?**
- ✅ Check that all required environment variables are set
- ✅ Verify your Stripe and Identify API keys are valid
- ✅ Make sure the `.env` file is in the correct location
## .env File Configuration
The server supports flexible .env file loading:
### Default Locations (checked in order)
1. `.env` (current directory)
2. `portal-server/.env` (portal-server subdirectory)
### Custom .env File Path
```bash
# Use custom .env file location
cargo run -- --from-env --env-file /path/to/custom/.env
```
### Environment Variables Priority
1. Command line arguments (highest priority)
2. .env file values
3. System environment variables
4. Default values (lowest priority)
## API Endpoints
### KYC Verification
- `POST /api/kyc/create-verification-session` - Create a new KYC verification session
- `POST /api/kyc/verification-result-webhook` - Handle verification results from Identify
- `POST /api/kyc/is-verified` - Check if a user is verified
### Payment Processing
- `POST /api/company/create-payment-intent` - Create payment intent for company registration
- `POST /api/resident/create-payment-intent` - Create payment intent for resident registration
- `GET /api/company/payment-success` - Payment success redirect
- `GET /api/company/payment-failure` - Payment failure redirect
- `POST /api/webhooks/stripe` - Handle Stripe webhooks
### Health Check
- `GET /api/health` - Server health check
## Usage
### Command Line
```bash
# Run with command line arguments
./portal-server \
--host 0.0.0.0 \
--port 3001 \
--stripe-secret-key sk_test_... \
--stripe-publishable-key pk_test_... \
--identify-api-key identify_... \
--api-keys dev_key_123,prod_key_456 \
--static-dir ./static
# Run with .env file (recommended)
./portal-server --from-env
# Run with custom .env file location
./portal-server --from-env --env-file /path/to/custom/.env
# Show help
./portal-server --help
```
### Environment Variables
Create a `.env` file or set these environment variables:
```bash
# Server configuration
HOST=127.0.0.1
PORT=3001
# Stripe configuration
STRIPE_SECRET_KEY=sk_test_...
STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
# Identify KYC configuration
IDENTIFY_API_KEY=identify_...
IDENTIFY_WEBHOOK_SECRET=your_identify_webhook_secret
IDENTIFY_API_URL=https://api.identify.com
# Security configuration
API_KEYS=api_key_1,api_key_2,api_key_3
# CORS configuration (use specific domains in production)
CORS_ORIGINS=https://app.freezone.com,https://portal.freezone.com
```
### Library Usage
```rust
use portal_server::{PortalServerBuilder, ServerConfig};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Load configuration
let config = ServerConfig::from_env()?;
// Build and run server
let server = PortalServerBuilder::new(config)
.with_static_dir("./static")
.build()
.await?;
server.run().await?;
Ok(())
}
```
## Configuration
### Command Line Options
- `--host` - Server host address (default: 127.0.0.1)
- `--port` - Server port (default: 3001)
- `--stripe-secret-key` - Stripe secret key (required)
- `--stripe-publishable-key` - Stripe publishable key (required)
- `--stripe-webhook-secret` - Stripe webhook secret (optional)
- `--identify-api-key` - Identify API key for KYC (required)
- `--identify-webhook-secret` - Identify webhook secret for signature verification (optional)
- `--api-keys` - API keys for authentication, comma-separated (optional)
- `--identify-api-url` - Identify API URL (default: https://api.identify.com)
- `--cors-origins` - CORS allowed origins, comma-separated (default: *)
- `--static-dir` - Directory to serve static files from (optional)
- `--from-env` - Load configuration from environment variables
- `--env-file` - Path to .env file (defaults to .env in current directory)
- `--verbose` - Enable verbose logging
### Required Environment Variables
When using `--from-env` flag, these environment variables are required:
- `STRIPE_SECRET_KEY` - Your Stripe secret key
- `STRIPE_PUBLISHABLE_KEY` - Your Stripe publishable key
- `IDENTIFY_API_KEY` - Your Identify API key for KYC verification
## Security & Build Modes
The server supports two build modes with different security configurations:
### Development Mode (Default)
- **CORS**: Permissive (allows all origins)
- **Purpose**: Local development and testing
- **Build**: `cargo build` or `cargo build --features dev`
### Production Mode
- **CORS**: Restricted to specified origins only
- **Purpose**: Production deployments
- **Build**: `cargo build --features prod --no-default-features`
### CORS Configuration
#### Development Mode
```bash
# Allows all origins for easy local development
cargo run -- --cors-origins "*"
```
#### Production Mode
```bash
# Restrict to your app domains only
cargo build --features prod --no-default-features
./target/release/portal-server --cors-origins "https://app.freezone.com,https://portal.freezone.com"
```
## Development
### Building
```bash
# Development build (default)
cargo build --release
# Production build with security restrictions
cargo build --release --features prod --no-default-features
```
### Running
```bash
# Development mode (permissive CORS)
cargo run -- --verbose
# Development with environment file
cargo run -- --from-env --verbose
# Production mode (restricted CORS)
cargo build --features prod --no-default-features
./target/release/portal-server --from-env --cors-origins "https://yourdomain.com"
```
### Testing
```bash
cargo test
```
## Security Recommendations
### Production Deployment
For production deployments, consider implementing additional security measures beyond CORS:
1. **API Key Authentication**: Add API key validation for sensitive endpoints
2. **Rate Limiting**: Implement rate limiting to prevent abuse
3. **Request Size Limits**: Set maximum request body sizes
4. **HTTPS Only**: Always use HTTPS in production
5. **Firewall Rules**: Restrict server access at the network level
6. **Environment Variables**: Never expose API keys in logs or error messages
### Current Security Features
**API Key Authentication**: All protected endpoints require valid API key in `x-api-key` header
**Webhook Signature Verification**: HMAC-SHA256 verification for both Stripe and Identify webhooks
**CORS Origin Restrictions**: Production mode restricts origins to specified domains
**Input Validation**: All endpoints validate request data
**Feature-based Configuration**: Separate dev/prod security policies
**Constant-time Comparison**: Secure signature verification to prevent timing attacks
### API Key Authentication
Protected endpoints require a valid API key in the `x-api-key` header:
```bash
# Example API call with authentication
curl -X POST http://localhost:3001/api/kyc/create-verification-session \
-H "Content-Type: application/json" \
-H "x-api-key: your_api_key_here" \
-d '{"user_id": "user123", "email": "user@example.com"}'
```
**Protected Endpoints:**
- All KYC endpoints (except webhooks)
- All payment endpoints (except webhooks and redirects)
- Legacy endpoints
**Unprotected Endpoints:**
- Health check (`/api/health`)
- Webhook endpoints (use signature verification instead)
### Additional Security (Recommended)
Consider implementing these additional security measures:
```rust
// Example: Rate limiting (not implemented)
async fn rate_limit(req: Request<Body>, next: Next<Body>) -> Response {
// Check request rate per IP
// Return 429 if exceeded
}
```
## API Examples
### Create KYC Verification Session
```bash
curl -X POST http://localhost:3001/api/kyc/create-verification-session \
-H "Content-Type: application/json" \
-H "x-api-key: your_api_key_here" \
-d '{
"user_id": "user123",
"email": "user@example.com",
"return_url": "https://yourapp.com/verification-complete",
"webhook_url": "https://yourapp.com/webhook"
}'
```
### Check Verification Status
```bash
curl -X POST http://localhost:3001/api/kyc/is-verified \
-H "Content-Type: application/json" \
-H "x-api-key: your_api_key_here" \
-d '{
"user_id": "user123"
}'
```
### Create Payment Intent
```bash
curl -X POST http://localhost:3001/api/company/create-payment-intent \
-H "Content-Type: application/json" \
-H "x-api-key: your_api_key_here" \
-d '{
"company_name": "Example Corp",
"company_type": "Startup FZC",
"company_email": "contact@example.com",
"payment_plan": "monthly",
"agreements": ["terms", "privacy"],
"final_agreement": true
}'
```
## Architecture
The server is built using:
- **Axum** - Web framework
- **Tokio** - Async runtime
- **Reqwest** - HTTP client for external APIs
- **Serde** - JSON serialization
- **Tracing** - Logging and observability
- **Clap** - Command-line argument parsing
The codebase is organized into:
- `src/lib.rs` - Library exports
- `src/config.rs` - Configuration management
- `src/models.rs` - Data models and types
- `src/services.rs` - External API integrations (Stripe, Identify)
- `src/handlers.rs` - HTTP request handlers
- `src/server.rs` - Server builder and configuration
- `cmd/main.rs` - Command-line interface
## License
This project is part of the FreeZone platform.