# 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, next: Next) -> 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.