18 Commits

Author SHA1 Message Date
99819b70ff added caddy-proxy-manager for testing
Some checks failed
Build and Push Docker Images (Trusted) / build-and-push (., docker/caddy/Dockerfile, caddy) (push) Has been cancelled
Build and Push Docker Images (Trusted) / build-and-push (., docker/l4-port-manager/Dockerfile, l4-port-manager) (push) Has been cancelled
Build and Push Docker Images (Trusted) / build-and-push (., docker/web/Dockerfile, web) (push) Has been cancelled
Tests / test (push) Has been cancelled
2026-04-21 22:49:08 +00:00
fuomag9
1237cdee4f Fix lint errors: remove unused imports and fix type assertions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:57:56 +02:00
fuomag9
3a16d6e9b1 Replace next-auth with Better Auth, migrate DB columns to camelCase
- Replace next-auth v5 beta with better-auth v1.6.2 (stable releases)
- Add multi-provider OAuth support with admin UI configuration
- New oauthProviders table with encrypted secrets (AES-256-GCM)
- Env var bootstrap (OAUTH_*) syncs to DB, UI-created providers fully editable
- OAuth provider REST API: GET/POST/PUT/DELETE /api/v1/oauth-providers
- Settings page "Authentication Providers" section for admin management
- Account linking uses new accounts table (multi-provider per user)
- Username plugin for credentials sign-in (replaces email@localhost pattern)
- bcrypt password compatibility (existing hashes work)
- Database-backed sessions via Kysely adapter (bun:sqlite direct)
- Configurable rate limiting via AUTH_RATE_LIMIT_* env vars
- All DB columns migrated from snake_case to camelCase
- All TypeScript types/models migrated to camelCase properties
- Removed casing: "snake_case" from Drizzle config
- Callback URL format: {baseUrl}/api/auth/oauth2/callback/{providerId}
- package-lock.json removed and gitignored (using bun.lock)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:11:48 +02:00
fuomag9
b7bd6b930a Revert "Move forward auth redirect URI from query string to HttpOnly cookie"
This reverts commit b6b53b7029.
2026-04-09 16:22:05 +02:00
fuomag9
b6b53b7029 Move forward auth redirect URI from query string to HttpOnly cookie
Replace the ?rd= query parameter in the Caddy→portal redirect with a
_cpm_rd HttpOnly cookie (Secure, SameSite=Lax, Path=/portal, 10min TTL).
The portal server component reads and immediately deletes the cookie,
then processes it through the existing validation and redirect intent flow.

This removes the redirect URI from the browser URL bar while maintaining
all existing security properties (domain validation, server-side storage,
one-time opaque rid).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 10:21:45 +02:00
fuomag9
fbf8ca38b0 Harden forward auth: store redirect URIs server-side, eliminate client control
Replace client-controlled redirectUri with server-side redirect intents.
The portal server component validates the ?rd= hostname against
isForwardAuthDomain, stores the URI in a new forward_auth_redirect_intents
table, and passes only an opaque rid (128-bit random, SHA-256 hashed) to
the client. Login endpoints consume the intent atomically (one-time use,
10-minute TTL) and retrieve the stored URI — the client never sends the
redirect URL to any API endpoint.

Security properties:
- Redirect URI is never client-controlled in API requests
- rid is 128-bit random, stored as SHA-256 hash (not reversible from DB)
- Atomic one-time consumption prevents replay
- 10-minute TTL limits attack window for OAuth round-trip
- Immediate deletion after consumption
- Expired intents cleaned up opportunistically
- Hostname validated against registered forward-auth domains before storage

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 18:12:01 +02:00
fuomag9
b81c211da9 Fix forward auth security vulnerabilities found during pentest
- Fix broken rate limiting: add registerFailedAttempt/resetAttempts calls
- Remove raw session token from exchange table; generate fresh token at redemption
- Fix TOCTOU race: atomic UPDATE...WHERE used=false for exchange redemption
- Delete exchange records immediately after redemption
- Change bcrypt.compareSync to async bcrypt.compare to prevent event loop blocking
- Fix IP extraction: prefer x-real-ip, fall back to last x-forwarded-for entry
- Restrict redirect URI scheme to http/https only
- Add Origin header CSRF check on login and session-login endpoints
- Remove admin auto-access bypass from checkHostAccess (deny-by-default for all)
- Revoke forward auth sessions when user status changes away from active
- Validate portal domain against registered forward-auth hosts to prevent phishing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 00:01:10 +02:00
fuomag9
03c8f40417 Add forward auth portal — CPM as built-in IdP replacing Authentik
CPM can now act as its own forward auth provider for proxied sites.
Users authenticate at a login portal (credentials or OAuth) and Caddy
gates access via a verify subrequest, eliminating the need for external
IdPs like Authentik.

Key components:
- Forward auth flow: verify endpoint, exchange code callback, login portal
- User groups with membership management
- Per-proxy-host access control (users and/or groups)
- Caddy config generation for forward_auth handler + callback route
- OAuth and credential login on the portal page
- Admin UI: groups page, inline user/group assignment in proxy host form
- REST API: /api/v1/groups, /api/v1/forward-auth-sessions, per-host access
- Integration tests for groups and forward auth schema

Also fixes mTLS E2E test selectors broken by the RBAC refactor.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 22:32:17 +02:00
fuomag9
77e354cd7c feat: rewrite auth pages with shadcn
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 13:29:55 +01:00
fuomag9
73c90894b1 Handle wildcard proxy hosts and stabilize test coverage
- accept wildcard proxy host domains like *.example.com with validation and normalization
- make exact hosts win over overlapping wildcards in generated routes and TLS policies
- add unit coverage for host-pattern priority and wildcard domain handling
- add a single test:all entry point and clean up lint/typecheck issues so the suite runs cleanly
- run mobile layout Playwright checks under both chromium and mobile-iphone
2026-03-14 01:03:34 +01:00
fuomag9
75044c8d9b fix: harden security post-review (JWT exposure, rate limiter, token expiry, timing)
- Raw JWT never sent to browser: page.tsx uses peekLinkingToken (read-only),
  client sends opaque linkingId, API calls retrieveLinkingToken server-side
- link-account rate limiter now uses isRateLimited/registerFailedAttempt/
  resetAttempts correctly (count only failures, reset on success)
- linking_tokens gains expiresAt column (indexed) + opportunistic expiry
  purge on insert to prevent unbounded table growth
- secureTokenCompare fixed: pad+slice to expected length so timing is
  constant regardless of submitted token length (no length leak)
- autoLinkOAuth uses config.oauth.allowAutoLinking (boolean) instead of
  process.env truthy check that mishandles OAUTH_ALLOW_AUTO_LINKING=false
- Add Permissions-Policy header; restore X-Frame-Options for legacy UAs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-25 20:58:21 +01:00
fuomag9
9a189ea342 fix: store OAuth linking token server-side, remove JWT from URL and audit log
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-25 09:31:27 +01:00
fuomag9
be21f46ad5 Added user tab and oauth2, streamlined readme 2025-12-28 15:14:56 +01:00
fuomag9
ad0225a16e Throttle login attempts and lock admin actions to privileged sessions 2025-11-04 00:00:22 +01:00
fuomag9
668b667fe9 updated a lot of stuff 2025-11-02 22:16:13 +01:00
fuomag9
d9ced96e1b implement oauth2 login 2025-10-31 23:02:30 +01:00
fuomag9
29acf06f75 Swapped the entire UI to Material UI, applied a global dark theme, and removed all of the old styled-jsx/CSS-module styling 2025-10-31 21:03:02 +01:00
fuomag9
315192fb54 first rewrite commit 2025-10-31 20:08:28 +01:00