Security Architecture

Overview

The Refresh App Web implements defense-in-depth security with multiple layers of protection: network security, authentication via FusionAuth, authorization via role-based permissions, data protection, and application security. This document describes the comprehensive security model.

Security Layers

┌─────────────────────────────────────────────────────────────────┐
│                    Network Security                              │
│  • HTTPS enforcement                                             │
│  • HSTS, CSP, security headers                                   │
│  • CORS policies                                                 │
└───────────────────┬─────────────────────────────────────────────┘

┌───────────────────▼─────────────────────────────────────────────┐
│                  Authentication (FusionAuth)                     │
│  • OAuth 2.0 / OIDC                                              │
│  • Self-registration with verification                           │
│  • MFA support                                                   │
│  • M2M via Entity Grants                                         │
└───────────────────┬─────────────────────────────────────────────┘

┌───────────────────▼─────────────────────────────────────────────┐
│                  Authorization                                   │
│  • FusionAuth roles → Database permissions                       │
│  • Granular resource:action permissions                          │
│  • Row-Level Security (RLS)                                      │
└───────────────────┬─────────────────────────────────────────────┘

┌───────────────────▼─────────────────────────────────────────────┐
│                  Data Protection                                 │
│  • Encryption in transit (TLS 1.3)                               │
│  • Tenant isolation via RLS                                      │
│  • Personal vs work data separation                              │
│  • Secret management (AWS SSM, Cloudflare)                       │
└───────────────────┬─────────────────────────────────────────────┘

┌───────────────────▼─────────────────────────────────────────────┐
│              Application Security                                │
│  • Input validation (Zod schemas)                                │
│  • XSS protection                                                │
│  • CSRF protection                                               │
│  • SQL injection prevention (Drizzle ORM)                        │
└─────────────────────────────────────────────────────────────────┘

Authentication Security

FusionAuth handles all identity concerns. See Authentication Flow for complete details.

Key Security Properties

Property
Value

JWT Algorithm

RS256 (asymmetric)

Access Token TTL

60 minutes

Refresh Token TTL

30 days

MFA

TOTP, SMS (configurable)

Self-Registration

Enabled with email verification

Self-Registration Safeguards

  1. Email verification required - Must verify before full access

  2. No default tenant access - New users get personal account only

  3. HRIS-based provisioning - Work accounts created by sync, not self-registration

  4. Rate limiting - FusionAuth limits registration attempts

Authorization Security

See Authorization for the complete role and permission model.

Key Security Properties

Layer
What It Enforces

Application

Permission checks before API operations

RLS

Database-level tenant isolation (cannot be bypassed)

Row-Level Security (RLS)

RLS prevents data leakage at the database level using two key functions:

auth_user() - Resolves FusionAuth JWT sub to internal user_id:

get_permission() - Returns permission check with bypass info:

Example RLS Policy with bypass support:

Benefits:

  • Cannot be bypassed from application code

  • Enforced by PostgreSQL on every query

  • Automatic filtering without explicit WHERE clauses

  • Permission checks happen at database level

  • bypass_rls allows internal employees to access all tenants for support

  • Identity resolution is database-side (future-proof for api-core migration)

Data Protection

Encryption in Transit

Connection
Encryption

Browser → App

TLS 1.3 (Cloudflare)

App → FusionAuth

TLS 1.3

App → Neon DB

TLS 1.3

Service → Service

TLS 1.3

Encryption at Rest

Storage
Encryption

Neon Postgres

AES-256 (Neon managed)

Cloudflare R2

AES-256 (Cloudflare managed)

FusionAuth

AES-256 (FusionAuth managed)

Tenant Data Isolation

Multi-layer isolation ensures tenants can never access each other's data:

  1. Identity Layer - FusionAuth user → user_identities → internal user_id

  2. Membership Layer - tenant_users validates access

  3. Data Layer - RLS policies filter by tenant_id

Personal vs Work Data Separation

Personal data (therapy sessions, anonymous reports) is owned by the personal user_id and never visible to tenant admins. Work data (surveys, HRIS records) is owned by the work user_id.

See User Management for the complete data ownership model.

Secret Management

AWS SSM Parameter Store:

  • Encrypted with AWS KMS

  • IAM role-based access

  • Retrieved during deployment

Cloudflare Secrets:

  • Uploaded via Wrangler CLI

  • Encrypted in Workers

  • Accessed via env object

Network Security

HTTPS Enforcement

Security Headers

CORS Policy

Application Security

Input Validation

Email Normalization

Critical: All email handling must be case-insensitive to prevent identity matching failures.

Apply to:

  • Identity resolution (FusionAuth JWT email → user_identities)

  • Account linking (verification of ownership)

  • Notification routing

  • HRIS sync email matching

XSS Prevention

  • Svelte automatically escapes output

  • {@html} only with sanitized content

  • CSP headers (when enabled)

CSRF Protection

  • SameSite cookies (lax)

  • Origin header validation

  • State parameter in OAuth flow

SQL Injection Prevention

Drizzle ORM with parameterized queries:

Attack Prevention

Attack
Prevention

Credential stuffing

FusionAuth rate limiting, account lockout

Session hijacking

HTTP-only cookies, short JWT lifetime

Token forgery

RS256 signing, JWKS validation

Tenant ID tampering

JWT-embedded tenant_id, RLS enforcement

Cross-tenant access

RLS policies, tenant_users validation

XSS

Svelte escaping, CSP, sanitization

CSRF

SameSite cookies, origin validation

SQL injection

Drizzle ORM, parameterized queries

Privilege escalation

Server-side permission checks

Audit Logging

Events to Log

Event
Data Captured

Login success/failure

User, IP, timestamp, method

Permission denied

User, resource, required permission

Data export

User, tenant, data type

Role changes

Admin, target user, old/new role

HRIS sync

Tenant, records processed

Account linking

User, identities linked

Log Structure

Compliance

GDPR

Requirement
Implementation

Data minimization

Only collect necessary data

Right to access

User can view all their data

Right to rectification

User can update their data

Right to erasure

User can request deletion

Data portability

Export functionality

Consent

Privacy policy acceptance

Data Deletion Flow

Security Checklist

Before Deployment

Regular Audits

Incident Response

Security Monitoring

  • Cloudflare Analytics (request patterns, errors)

  • FusionAuth logs (authentication events)

  • Application logs (permission denials)

Key Metrics

  • Failed login attempts

  • 401/403 errors

  • Unusual request patterns

  • Large data exports

  • Cross-tenant access attempts


Last updated: December 2025

Last updated