🔒 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).
  • Token Rotation: On access token expiration, the frontend must request /auth/refresh using 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: bcrypt or Argon2id (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 localhost and 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:
    1. Extract slip_trans_id from the Mini-QR using the AI/OCR service.
    2. Check the database payments table for existing records with the same slip_trans_id.
    3. If present, reject the slip immediately as DUPLICATE_SLIP to prevent double-spending.

3.2 Automated Validation Checks

All uploaded slips must pass the following checks:

  1. 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.
  2. Amount Verification: The verified amount returned by the bank API must exactly match the user’s expense_shares.share_amount.
  3. Receiver Verification: The receiver account number or name in the bank response must match the bill creator’s PromptPay/bank details registered in SplitDee.
  4. 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 safety or pip-audit.