books/backend/Books.Api/Database/Migrations/002_ApiKeys.sql
Nicolaj Hartmann 926085eeab Add OpenID Connect + API Key authentication
Backend:
- Cookie + OIDC + API Key authentication schemes
- ApiKeyAuthenticationHandler with SHA-256 validation and 24h cache
- AuthController with login/logout/profile endpoints
- API Key domain model (EventFlow aggregate, events, commands)
- ApiKeyReadModel and repository for key validation
- Database migration 002_ApiKeys.sql
- CORS configuration for frontend

Frontend:
- authService.ts for login/logout/profile API calls
- authStore.ts (Zustand) for user context state
- ProtectedRoute component for route guards
- Header updated with user display and logout
- GraphQL client with credentials: include

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 11:49:29 +01:00

21 lines
852 B
SQL

-- API Keys table for programmatic access authentication
CREATE TABLE IF NOT EXISTS apikey_read_models (
aggregate_id VARCHAR(255) PRIMARY KEY,
create_time TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_time TIMESTAMPTZ NOT NULL DEFAULT NOW(),
last_aggregate_sequence_number INT NOT NULL DEFAULT 1,
name VARCHAR(255) NOT NULL,
key_hash VARCHAR(64) NOT NULL,
company_id VARCHAR(255) NOT NULL,
created_by VARCHAR(255) NOT NULL,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
revoked_time TIMESTAMPTZ,
revoked_by VARCHAR(255)
);
-- Index for looking up API keys by company
CREATE INDEX IF NOT EXISTS idx_apikey_company ON apikey_read_models(company_id);
-- Partial index for efficient lookups of active API keys
CREATE INDEX IF NOT EXISTS idx_apikey_active ON apikey_read_models(aggregate_id) WHERE is_active = true;