414 lines
12 KiB
Markdown
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. |