Skip to content

feat: Easier Deployment - Optional Postgres, Auth Off, and Flexible Auth Providers #16

@Fortinbra

Description

@Fortinbra

Overview

This feature significantly lowers the barrier to entry for new users by providing a "batteries-included" deployment option that requires minimal configuration. It introduces three major capabilities:

  1. All-in-one Docker Compose file that includes PostgreSQL
  2. Disable authentication for demo/family use
  3. Alternative OIDC providers beyond Authentik (Google, Microsoft, Auth0, Keycloak)

Goal: Enable a new user to go from git clone to a running application in under 5 minutes with a single docker compose up command.

Priority: High
Dependencies: Feature 056 (API Config Endpoint - Complete)


Problem Statement

Current friction points:

  1. External PostgreSQL required — users must set up and configure their own database before deploying
  2. Mandatory Authentik — API throws InvalidOperationException if Authority is not configured
  3. Complex configuration — users must understand ASP.NET Core configuration, environment variables, and OIDC concepts
  4. No "try before you commit" path — no way to evaluate the app without significant infrastructure investment

Target state:

  • docker compose -f docker-compose.demo.yml up starts everything with sensible defaults
  • Authentication can be disabled entirely for single-user/family deployments
  • Users can choose from Authentik (default), Google, Microsoft, Auth0, Keycloak, or any generic OIDC provider
  • Clear upgrade path from demo to production

User Stories

Easy Deployment

US-055-001: One-Command Demo Deployment
As a new user evaluating BudgetExperiment, I want to start the entire application with a single command so that I can try out the features without complex infrastructure setup.

  • docker compose -f docker-compose.demo.yml up starts API, Client, and PostgreSQL
  • PostgreSQL is pre-configured with correct schema (auto-migration)
  • Application is accessible at http://localhost:5099
  • No external configuration required for basic operation
  • README includes quick-start instructions for demo mode
  • Demo mode uses auth-off by default for simplest experience

US-055-002: Persistent Demo Data
As a demo user, I want my data to persist between container restarts so that I don't lose work during evaluation.

  • PostgreSQL data stored in a named Docker volume
  • Volume survives docker compose down (requires -v to remove)
  • Documentation explains how to reset/clear demo data

Authentication Off Mode

US-055-003: Disable Authentication via Configuration
As a single-user or family deployer, I want to disable authentication entirely so I don't need to set up an identity provider.

  • Setting Authentication__Mode=None disables all auth middleware
  • All API requests are treated as authenticated
  • A default "family" user context is applied (well-known GUID 00000000-0000-0000-0000-000000000001)
  • API returns proper user context for data scoping

US-055-004: UI Adapts to Auth-Off Mode
As a user running in auth-off mode, I want to not see login/logout/profile UI elements.

  • Client fetches auth mode from /api/v1/config endpoint
  • When mode is "none": hide Login, Logout, User profile/avatar
  • NavBar shows app name or "Family Budget" instead of user info
  • Authentication routes redirect to home

US-055-005: Security Warning in Auth-Off Mode
As an administrator, I want to see a clear warning when running in auth-off mode.

  • API logs a WARNING at startup when Authentication:Mode=None
  • UI shows a subtle banner: "Running in demo mode - authentication disabled"
  • Banner links to documentation about enabling auth

Flexible OIDC Providers

US-055-006: Google OAuth

  • Authentication__Provider=Google enables Google OAuth
  • Required: ClientId, ClientSecret
  • Documentation explains Google Cloud Console setup

US-055-007: Microsoft Entra ID

  • Authentication__Provider=Microsoft enables Microsoft auth
  • Required: ClientId, TenantId
  • Supports single-tenant and multi-tenant

US-055-008: Generic OIDC Provider

  • Authentication__Provider=OIDC enables generic OIDC
  • Required: Authority, ClientId, ClientSecret (if confidential), Scopes
  • Claim mapping is configurable
  • Works with Keycloak, Auth0, Okta

US-055-009: Maintain Authentik as Default

  • Authentication__Provider=Authentik (or unset) uses current Authentik flow
  • All existing config keys continue to work
  • No breaking changes to docker-compose.pi.yml or .env files

Technical Design

Configuration Schema

public sealed class AuthenticationOptions
{
    public const string SectionName = "Authentication";
    public string Mode { get; set; } = "OIDC";           // "None" or "OIDC"
    public string Provider { get; set; } = "Authentik";   // "Authentik", "Google", "Microsoft", "OIDC"
    public AuthentikProviderOptions Authentik { get; set; } = new();
    public GoogleProviderOptions Google { get; set; } = new();
    public MicrosoftProviderOptions Microsoft { get; set; } = new();
    public GenericOidcProviderOptions Oidc { get; set; } = new();
}

No-Auth Handler

A custom AuthenticationHandler<AuthenticationSchemeOptions> that always succeeds, returning claims for the family user (00000000-0000-0000-0000-000000000001, "Family", "family@localhost").

/api/v1/config Response Updates

// Mode = None
{ "authentication": { "mode": "none" } }

// Mode = OIDC (any provider)
{ "authentication": { "mode": "oidc", "provider": "authentik", "oidc": { "authority": "...", "clientId": "..." } } }

New/Modified Files

File Status Description
Api/AuthenticationOptions.cs New Unified auth config
Api/Authentication/NoAuthHandler.cs New Handler for Mode=None
Api/Authentication/FamilyUserContext.cs New Default user context
Api/Authentication/AuthenticationConfigurator.cs New Factory for provider config
Client/Shared/AuthOffBanner.razor New Warning banner
docker-compose.demo.yml New All-in-one demo compose
docs/AUTH-PROVIDERS.md New Per-provider setup guide

Implementation Phases

Phase 1: AuthenticationOptions Refactoring

  • Create AuthenticationOptions with nested provider options
  • Create mode/provider constants
  • Update ConfigureAuthentication in Program.cs
  • Maintain backward compatibility with existing Authentik config
  • Unit tests for configuration binding

Phase 2: No-Auth Mode

  • Create NoAuthHandler authentication handler
  • Create FamilyUserContext with well-known user constants
  • Detect Mode=None and register NoAuthHandler
  • Log startup WARNING
  • Update /api/v1/config to return mode: "none"
  • Unit + integration tests

Phase 3: Client Auth-Off Adaptations

  • Update AuthStateService for mode: "none"
  • Create AuthOffBanner.razor
  • Hide login/logout/profile in NavMenu when auth is off
  • Redirect /authentication/* routes to home
  • bUnit tests for conditional rendering

Phase 4: Google OAuth Provider

  • Implement Google JWT Bearer config
  • Google-specific claim mapping
  • Update /api/v1/config for Google
  • Documentation for Google Cloud Console setup
  • Integration tests

Phase 5: Microsoft Entra ID Provider

  • Implement Microsoft JWT Bearer config
  • Single-tenant and multi-tenant support
  • Documentation for Azure AD app registration
  • Integration tests

Phase 6: Generic OIDC Provider

  • Generic OIDC JWT Bearer config
  • Configurable claim mappings and scopes
  • Documentation for Keycloak, Auth0, Okta examples
  • Integration tests

Phase 7: Demo Docker Compose

  • Create docker-compose.demo.yml with PostgreSQL + API
  • Configure persistent volume, health checks
  • Default Authentication__Mode=None
  • Test on clean Docker environment and ARM64

Phase 8: Documentation

  • Create docs/AUTH-PROVIDERS.md
  • Update README with quick-start section
  • Update .env.example
  • Troubleshooting section

Phase 9: Testing & Validation

  • Playwright E2E tests for no-auth mode
  • API integration tests for provider switching
  • Migration testing (demo → production)
  • Security review of no-auth implementation

Security Considerations

⚠️ No-auth mode should NEVER be exposed to the public internet.

Mitigations:

  • Startup warning log
  • UI banner reminder
  • Documentation warnings
  • Demo compose uses localhost:5099 only
  • No HTTPS in demo (signals local-only)

Environment Variables Reference

Authentication__Mode=OIDC                    # "None" or "OIDC"
Authentication__Provider=Authentik           # "Authentik", "Google", "Microsoft", "OIDC"

# Authentik
Authentication__Authentik__Authority=https://auth.example.com/application/o/budget/
Authentication__Authentik__Audience=budget-experiment
Authentication__Authentik__ClientId=abc123

# Google
Authentication__Google__ClientId=123456789-xyz.apps.googleusercontent.com
Authentication__Google__ClientSecret=GOCSPX-xxxxx

# Microsoft
Authentication__Microsoft__ClientId=00000000-0000-0000-0000-000000000000
Authentication__Microsoft__TenantId=common

# Generic OIDC
Authentication__Oidc__Authority=https://keycloak.example.com/realms/master
Authentication__Oidc__ClientId=budget-experiment
Authentication__Oidc__ClientSecret=xxx

Out of Scope

  • Production hardening for demo PostgreSQL
  • SSO/SCIM/advanced user management
  • Multi-user management in no-auth mode
  • Social login UI ("Login with Google" button)
  • Session management UI

Success Metrics

  • Time to First Deploy: < 5 minutes for demo mode
  • Backward Compatibility: 100% of existing deployments continue to work
  • Documentation Coverage: 100% of auth options documented with examples

Migrated from docs/055-easy-deployment-auth-options.md

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions