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

12 KiB

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 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:

# 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:

# 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

# 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:

# 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

# 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

# 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:

# 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

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

# Allows all origins for easy local development
cargo run -- --cors-origins "*"

Production Mode

# 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

# Development build (default)
cargo build --release

# Production build with security restrictions
cargo build --release --features prod --no-default-features

Running

# 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

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:

# 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)

Consider implementing these additional security measures:

// 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

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

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

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.