Skip to content

ADR-001: Keycloak vs Auth0 for Authentication

Status: ✅ Accepted Date: 2024-08 Deciders: Development Team, CTO Related: ADR-002, ADR-004

Context

Noumaris is a healthcare SaaS platform handling sensitive clinical data. We need a robust authentication and authorization system that:

  • Supports HIPAA compliance requirements
  • Provides JWT-based authentication for frontend and backend
  • Enables role-based access control (RBAC)
  • Supports multi-tenancy (multiple institutions)
  • Allows customization of login/registration flows
  • Has reasonable costs for a bootstrapped startup

Decision

Selected: Keycloak (self-hosted, open-source)

We will use Keycloak as our identity and access management (IAM) solution, deployed on Google Cloud Run alongside our other services.

Rationale

Alternatives Considered

Option 1: Auth0 (SaaS)

Pros:

  • Fully managed service (no maintenance)
  • Great documentation and DX
  • Quick setup
  • Built-in security features

Cons:

  • Cost: $228/month (Essentials plan for 500 MAU) → $1,000+/month as we scale
  • Vendor lock-in: Difficult to migrate away
  • HIPAA compliance: Requires Business Associate Agreement (BAA) - only on Enterprise plan ($$$)
  • Data residency: Limited control over where data is stored
  • Customization limits: Restricted template customization

Verdict: ❌ Rejected - Too expensive for MVP, HIPAA compliance requires enterprise pricing

Option 2: Supabase Auth

Pros:

  • Open-source
  • PostgreSQL-based (familiar)
  • Great DX with JavaScript SDK
  • Affordable pricing

Cons:

  • Less mature than Keycloak or Auth0
  • Fewer enterprise features
  • Limited RBAC capabilities
  • Self-hosting required for HIPAA compliance
  • Smaller community and ecosystem

Verdict: ❌ Rejected - Not mature enough for healthcare use case

Option 3: AWS Cognito

Pros:

  • Fully managed AWS service
  • Integrates with AWS ecosystem
  • HIPAA compliant (with BAA)
  • Reasonable pricing

Cons:

  • AWS vendor lock-in
  • Complex configuration
  • Limited customization of UI
  • Not as flexible for custom workflows
  • We're using Google Cloud, not AWS

Verdict: ❌ Rejected - Cloud provider mismatch, limited customization

Option 4: Keycloak (SELECTED)

Pros:

  • Open-source and free
  • Self-hosted - Full control over data and infrastructure
  • HIPAA-ready - Can deploy in compliant manner
  • Mature and battle-tested - Used by major enterprises
  • Full customization - Custom themes, login flows, extensions
  • Standard protocols - OAuth2, OpenID Connect, SAML
  • Multi-tenancy support - Realms for different institutions
  • Cost-effective - Only infrastructure costs (~$50-100/month on Cloud Run)
  • Active community - Large ecosystem, good documentation

Cons:

  • Requires hosting and maintenance effort
  • Steeper learning curve than Auth0
  • Need to manage updates and security patches
  • More complex initial setup

Verdict:SELECTED

Consequences

Positive

  1. Cost Savings: $300/month saved vs Auth0 ($228/month Auth0 vs ~$50/month Cloud Run)
  2. HIPAA Compliance: Full control enables BAA compliance without enterprise pricing
  3. Flexibility: Can customize every aspect of auth flow
  4. Data Sovereignty: Patient data stays in our infrastructure
  5. No Vendor Lock-in: Can migrate or self-host anywhere
  6. Scalability: Horizontal scaling with Cloud Run

Negative

  1. Operational Overhead: Need to monitor, update, and maintain Keycloak
  2. Initial Setup Time: More complex than Auth0
  3. DevOps Complexity: Managing Docker images, deployments, backups
  4. Security Responsibility: We're responsible for security patches

Mitigations

  1. Automation: Use Terraform for infrastructure as code (ADR-004)
  2. Monitoring: Set up health checks, alerts, logging
  3. Documentation: Comprehensive setup guides for team
  4. Backup Strategy: Automated database backups to Google Cloud Storage
  5. Security: Subscribe to Keycloak security mailing list, automated updates

Implementation Notes

Deployment Architecture

┌─────────────────────────────────────┐
│     Frontend (React)                │
│  - Keycloak-js for login            │
│  - JWT token in localStorage        │
└─────────────────────────────────────┘

┌─────────────────────────────────────┐
│     Keycloak (Cloud Run)            │
│  - Port: 8080 (8081 local)          │
│  - Realm: noumaris                  │
│  - PostgreSQL backend               │
└─────────────────────────────────────┘

┌─────────────────────────────────────┐
│     Backend API (FastAPI)           │
│  - Validates JWT with public key    │
│  - Extracts roles from token        │
└─────────────────────────────────────┘

Configuration Approach

  • Local Development: Docker Compose with auto-import realm configuration
  • Production: Terraform-managed configuration (ADR-004)
  • Themes: Custom React-based theme using Keycloakify (ADR-002)

Roles & Permissions

  • Realm Roles: superadmin, institution_admin, resident, user
  • JWT Claims: realm_access.roles array
  • Backend Validation: Decorators (@require_superadmin, @require_institution_admin)

References

Internal documentation for Noumaris platform