Security
Monetro security architecture overview.
Encryption
- AES-256-GCM for sensitive fields at rest (IBANs, BICs, OAuth tokens, API credentials)
- Plaintext only exists in RAM during processing, never persisted to disk
- Encrypted values are never returned in API responses — only
secretSet: true/falseindicators
Authentication
- JWT Dual-Token: 15-minute access token + 7-day httpOnly refresh cookie
- 2FA: TOTP (Google Authenticator, Authy, Bitwarden) + WebAuthn/Passkeys (Touch ID, Face ID, YubiKey)
- Biometric: Native mobile login (Face ID / Touch ID via Capacitor)
- Backup codes provided during 2FA setup (one-time use)
Account Lockout
Progressive lockout after failed login attempts:
| Failed Attempts | Lockout Duration |
|---|---|
| 5 | 5 minutes |
| 10 | 10 minutes |
| 15 | 15 minutes |
| 20+ | 60 minutes |
Lockout expires automatically.
Rate Limiting
| Endpoint | Limit |
|---|---|
Login (/api/auth/login) | 10 requests / 15 min (per email) |
| Registration | 5 requests / 60 min (per IP) |
| Forgot Password | 5 requests / 60 min (per IP) |
| 2FA Verify | 10 requests / 15 min |
| General API | 300 requests / min (per IP) |
| Webhooks | 30 requests / min (per IP) |
429 Too Many Requests responses include Retry-After header.
Role-Based Access Control (RBAC)
Four roles with increasing permissions:
| Role | Description |
|---|---|
viewer | Read-only access to reports and invoices |
member | Create invoices, basic operations |
manager | Invoice/customer management, team capabilities |
admin | Full system access, user management, settings |
Data Isolation
- Multi-Tenant: All data strictly isolated by
tenantId - Every API query is automatically scoped to the authenticated user's tenant
- No cross-tenant data access possible
Webhook Security
Incoming webhooks from payment providers are verified using provider-specific signatures:
- Stripe:
Stripe-Signature(HMAC-SHA256) - PayPal: CRC32-based HMAC
- Mollie: API key fetch verification
- Revolut:
Revolut-Signature(HMAC-SHA256 + timestamp)
Each tenant has a unique webhook token (UUID) in the URL path: /api/payment-import/{provider}/{token}
Infrastructure
- Hosting: Hetzner VPS (Germany, EU)
- TLS: Automatic Let's Encrypt via Traefik
- DNS/DDoS: Cloudflare proxy
- No third-country data transfers in the managed variant
- DSGVO/GDPR compliant: Data processing within EU only
Audit Trail
All CREATE/UPDATE/DELETE actions are logged with:
- User ID and name
- Timestamp
- Action type and description
- 365-day retention (configurable)