🔒 Security Policy & Guidelines
This document outlines the security policies, cryptography standards, threat models, and mitigation strategies implemented in the SplitDee platform.
1. Authentication & Authorization (AuthN & AuthB)
1.1 JWT Token Strategy
SplitDee utilizes JSON Web Tokens (JWT) for stateless session authentication.
- Algorithm: HMAC SHA-256 (
HS256). - Token Types:
- Access Token: Short-lived (15 minutes). Sent via HTTP header:
Authorization: Bearer <token>. - Refresh Token: Long-lived (7 days). Stored securely in HttpOnly, Secure, SameSite=Strict cookies to mitigate Cross-Site Scripting (XSS) and Cross-Site Request Forgery (CSRF).
- Access Token: Short-lived (15 minutes). Sent via HTTP header:
- Token Rotation: On access token expiration, the frontend must request
/auth/refreshusing the refresh token. This rotates both the Access and Refresh tokens. - Revocation/Blacklisting: Active sessions can be revoked on logout or token compromise by storing revoked JTI (JWT ID) claims in Redis with a TTL matching the token’s expiration.
1.2 Password Hashing
- Algorithm:
bcryptorArgon2id(preferred). - Configuration: Minimum work factor of 12 for bcrypt.
- Policy: Enforce minimum 8 characters, requiring at least one uppercase letter, one lowercase letter, one number, and one special character. No passwords stored in plaintext.
2. API Security & Network Protection
2.1 CORS Setup
The FastAPI backend restricts Cross-Origin Resource Sharing (CORS) strictly to authorized domains.
- Development: Allow
localhostand specific IP addresses used by mobile simulators. - Production: Allow only the official web dashboard domain and verified frontend origins.
- Header Config:
allow_origins = ["https://splitdee.com", "https://api.splitdee.com"] allow_credentials = True allow_methods = ["GET", "POST", "PUT", "DELETE", "OPTIONS"] allow_headers = ["Authorization", "Content-Type", "X-Requested-With"]
2.2 Rate Limiting
To prevent Denial of Service (DoS) and brute-force attacks, endpoint-specific rate limiting is applied:
- Auth Endpoints (
/auth/login,/auth/signup): Max 5 requests per minute per IP. - API Endpoints (General): Max 100 requests per minute per authenticated user.
- Slip Upload Endpoint (
/bills/{id}/payments): Max 10 requests per minute per user. - Implementation: Redis-backed sliding window rate limiter implemented as FastAPI middleware.
3. Slip Verification Safety & Fraud Prevention
The AI Slip Verification service represents a critical financial risk vector (e.g., duplicate slips, modified images, fake slip generators).
3.1 Double-Spending Prevention
- Constraint: Each bank transaction has a unique
slip_trans_id(transaction reference ID). - Validation:
- Extract
slip_trans_idfrom the Mini-QR using the AI/OCR service. - Check the database
paymentstable for existing records with the sameslip_trans_id. - If present, reject the slip immediately as DUPLICATE_SLIP to prevent double-spending.
- Extract
3.2 Automated Validation Checks
All uploaded slips must pass the following checks:
- Bank API Verification: The backend query must match the transaction data with the bank partner/intermediary API (e.g., SlipOK, EasySlip) to verify the transaction actually exists.
- Amount Verification: The verified amount returned by the bank API must exactly match the user’s
expense_shares.share_amount. - Receiver Verification: The receiver account number or name in the bank response must match the bill creator’s PromptPay/bank details registered in SplitDee.
- Time Window Check: The transaction timestamp must be after the bill creation timestamp.
4. Data Privacy & Compliance (PDPA)
SplitDee stores Personally Identifiable Information (PII) including email addresses, phone numbers (used for PromptPay QR generation), display names, and avatars.
- Consent Management: Users must explicitly consent to the Privacy Policy and Terms of Service upon signup.
- Encryption at Rest: Sensitive PII columns (e.g.,
phone_number,email) are encrypted at rest using AES-256. - Right to Be Forgotten: Users can request account deletion. Deletion cascades to personal data, but transaction ledger history is anonymized rather than deleted to preserve the financial integrity of other groups.
- Storage Protection: Slip images are uploaded to AWS S3 / Google Cloud Storage buckets configured with private access controls and served via time-limited pre-signed URLs.
5. Security Checklist for Developers
- No raw SQL queries to prevent SQL Injection (use SQLAlchemy ORM parameter binding).
- Inputs validated using Pydantic schemas before processing.
- Error messages do not leak system internals (e.g., database stack traces) to clients.
- Dependency vulnerabilities checked regularly using tools like
safetyorpip-audit.