Commit Graph

30 Commits

Author SHA1 Message Date
Dan Milne
406a79d9eb Block SSRF via backchannel_logout_uri
backchannel_logout_uri was validated only for scheme/HTTPS, so an admin (or a
compromised admin account) could point it at internal infrastructure — cloud
metadata (169.254.169.254), loopback, or RFC1918 hosts — and every user logout
would fire a server-side POST there.

Add PrivateAddressCheck (app/lib) and apply it as defense-in-depth:
- Application validation rejects URIs whose host is, or is a literal, internal
  address (loopback / private / link-local / 0.0.0.0 / localhost / metadata
  hostnames). Fast, DNS-free, immediate admin feedback.
- BackchannelLogoutJob re-checks at request time WITH DNS resolution and aborts
  (no retry) if the host resolves to a non-public address — covering URIs that
  predate the validation and public hostnames pointed at internal IPs.

Tests cover the address classification, the model validation, and updates an
existing test that used a localhost logout URI.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 08:14:45 +10:00
Dan Milne
bfad9c4e9d Generated monogram fallback + optional dark-mode icon per application
Some checks failed
CI / scan_ruby (push) Has been cancelled
CI / scan_js (push) Has been cancelled
CI / scan_container (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
CI / system-test (push) Has been cancelled
When an application has no icon attached, render a deterministic
monogram SVG instead of the generic picture-frame placeholder. Initials
are picked from capital letters in the name (ShelfLife -> SL); fall
back to the first two letters when fewer than two capitals exist
(Audiobookshelf -> AU). Background colour is hashed from the name for
stable per-app identity across visits.

Adds an optional second icon attachment, icon_dark, alongside the main
icon. When present, render a <picture> with a prefers-color-scheme:
dark source so the browser swaps automatically; when absent, the main
icon is used in both modes. The SVG sanitization, content-type fix,
and size/format validation now run over both attachments uniformly.

Bumps to 0.14.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-07 17:02:53 +10:00
Dan Milne
5b41db2c6a Fix FileNotFoundError when uploading an SVG icon
Some checks failed
CI / scan_ruby (push) Has been cancelled
CI / scan_js (push) Has been cancelled
CI / scan_container (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
CI / system-test (push) Has been cancelled
The sanitize_svg_icon before_validation callback called icon.download,
but Active Storage uploads pending blobs in before_save — so at
before_validation time the file only existed in the request tempfile,
not at the configured storage path. Read from the pending attachable
(UploadedFile / IO hash) instead. Guards against the recursive callback
that icon.attach would otherwise trigger by tracking the cleaned
attachable by object identity. Bumps to 0.13.1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-07 16:43:24 +10:00
Dan Milne
03dfdbd83a Default-deny access control with group flags and access enumeration
Some checks failed
CI / scan_ruby (push) Has been cancelled
CI / scan_js (push) Has been cancelled
CI / scan_container (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
CI / system-test (push) Has been cancelled
Replaces the implicit "empty allowed_groups means public" rule with
explicit default-deny across both OIDC and ForwardAuth. Adds two boolean
flags on Group — auto_assign (Keycloak-style auto-join on user create)
and admin (members can reach the admin panel) — and drops the
users.admin column entirely. Adds "Users with access" and "Accessible
applications" panels with via-group badges on the application/user show
pages.

BEHAVIOR CHANGE: a ForwardAuth app with no allowed_groups previously
bypassed authentication entirely; it now returns 403 like any other
unauthorized request. The data migration seeds an "everyone" group and
attaches it to all previously group-less apps to preserve behavior on
existing installs. An "admins" group is seeded and backfilled from any
user with the old admin column.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-07 15:53:27 +10:00
Dan Milne
2e427a0520 Add SvgScrubber to strip XSS payloads from uploaded app icons
Application#sanitize_svg_icon already runs a Loofah scrubber on every
icon upload, but the scrubber class itself was never tracked. Land it
along with tests covering the four shapes that matter:

- <script> elements stripped entirely
- on* event handlers (onload, onclick, …) removed but the carrying
  element preserved
- attribute values pointing at javascript:/data: URIs rejected
- benign icons round-trip unchanged

Writing the benign-icon test caught a real bug: the attribute allowlist
holds canonical SVG case (viewBox, preserveAspectRatio, gradientUnits,
…) but safe_attribute? downcases the incoming name before comparing,
so legitimate icons were silently losing those attributes on upload.
Fix by comparing against a precomputed lowercase lookup set; the
constant stays readable as canonical SVG case for documentation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 23:57:22 +10:00
Dan Milne
2235924f37 Harden OIDC, add SVG sanitization, improve form UX and security defaults
Remove PKCE plain method support (S256 only), enforce openid scope requirement,
filter to supported scopes, strip reserved claims from custom claims as
defense-in-depth, sanitize SVG icons with Loofah, add global input padding,
switch session cookies to SameSite=Lax, use Session.active scope, and remove
unsafe-eval from CSP.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 21:06:51 +10:00
Dan Milne
fd8785a43d Add API keys / bearer tokens for forward auth
Some checks failed
CI / scan_ruby (push) Has been cancelled
CI / scan_js (push) Has been cancelled
CI / scan_container (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
CI / system-test (push) Has been cancelled
Enables server-to-server authentication for forward auth applications
(e.g., video players accessing WebDAV) where browser cookies aren't
available. API keys use clk_ prefixed tokens stored as HMAC hashes.

Bearer token auth is checked before cookie auth in /api/verify.
Invalid tokens return 401 JSON (no redirect). Requests without
bearer tokens fall through to existing cookie flow unchanged.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 21:45:40 +11:00
Dan Milne
cc6d4fcc65 Add test files, update checklist
Some checks failed
CI / scan_ruby (push) Has been cancelled
CI / scan_js (push) Has been cancelled
CI / scan_container (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
CI / system-test (push) Has been cancelled
2026-01-05 23:28:55 +11:00
Dan Milne
d597ca8810 Fix tests 2026-01-01 14:52:24 +11:00
Dan Milne
93a0edb0a2 StandardRB fixes
Some checks failed
CI / scan_ruby (push) Has been cancelled
CI / scan_js (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
CI / system-test (push) Has been cancelled
2026-01-01 13:29:44 +11:00
Dan Milne
4b4afe277e Include auth_time in ID token. Switch from upsert -> find_and_create_by so we actually get sid values for consent on the creation of the record 2025-12-31 16:36:32 +11:00
Dan Milne
364e6e21dd Fixes for tests and AR Encryption
Some checks failed
CI / scan_ruby (push) Has been cancelled
CI / scan_js (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
CI / system-test (push) Has been cancelled
2025-12-31 16:08:05 +11:00
Dan Milne
71d59e7367 Remove plain text token from everywhere
Some checks failed
CI / scan_ruby (push) Has been cancelled
CI / scan_js (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
CI / system-test (push) Has been cancelled
2025-12-30 11:58:11 +11:00
Dan Milne
0761c424c1 Fix tests. Remove tests which test rails functionality
Some checks failed
CI / scan_ruby (push) Has been cancelled
CI / scan_js (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
CI / system-test (push) Has been cancelled
2025-12-30 00:18:19 +11:00
Dan Milne
d6029556d3 Add OIDC fixes, add prefered_username, add application-user claims 2025-11-25 16:29:40 +11:00
Dan Milne
038801f34b Add pkce
Some checks failed
CI / scan_ruby (push) Has been cancelled
CI / scan_js (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
CI / system-test (push) Has been cancelled
2025-11-09 10:21:29 +11:00
Dan Milne
fb14ce032f Strip out more inline javascript code. Encrypt backup codes and treat the backup codes attribute as a json array 2025-11-04 18:46:11 +11:00
Dan Milne
ef15db77f9 Massive refactor. Merge forward_auth into App, remove references to unimplemented OIDC federation and SAML features. Add group and user custom claims. Groups now allocate which apps a user can use
Some checks failed
CI / scan_ruby (push) Has been cancelled
CI / scan_js (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
CI / system-test (push) Has been cancelled
2025-11-04 13:21:55 +11:00
Dan Milne
cfab21b130 More tests 2025-10-28 08:27:19 +11:00
Dan Milne
8dd3e60071 Add a list_sign_in_at field for users so magick links work 2025-10-26 22:40:54 +11:00
Dan Milne
e4e7a0873e Fixes 2025-10-26 22:03:03 +11:00
Dan Milne
b5b1d94d47 Fix the CLINCH_HOST issue. 2025-10-26 21:59:27 +11:00
Dan Milne
52cfd6122c Typo. More tests 2025-10-26 20:42:18 +11:00
Dan Milne
227e29ce0a Fix/add some tests. Configure email sending address 2025-10-26 20:13:39 +11:00
Dan Milne
d98f777e7d Refactor email delivery and background jobs system
- Switch from SolidQueue to async job processor for simpler background job handling
- Remove SolidQueue gem and related configuration files
- Add letter_opener gem for development email preview
- Fix invitation email template issues (invitation_login_token method and route helper)
- Configure SMTP settings via environment variables in application.rb
- Add email delivery configuration banner on admin users page
- Improve admin users page with inline action buttons and SMTP configuration warnings
- Update development and production environments to use async processor
- Add helper methods to detect SMTP configuration and filter out localhost settings

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-26 16:30:02 +11:00
Dan Milne
0af3dbefed Remember that we concented.
Some checks failed
CI / scan_ruby (push) Has been cancelled
CI / scan_js (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
CI / system-test (push) Has been cancelled
2025-10-24 17:01:03 +11:00
Dan Milne
12e0ef66ed OIDC app creation with encrypted secrets and application roles
Some checks failed
CI / scan_ruby (push) Has been cancelled
CI / scan_js (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
CI / system-test (push) Has been cancelled
2025-10-24 14:47:24 +11:00
Dan Milne
fc9afcd1b7 Separate Forward auth into it's own models + controller
Some checks failed
CI / scan_ruby (push) Has been cancelled
CI / scan_js (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
CI / system-test (push) Has been cancelled
2025-10-24 10:56:27 +11:00
Dan Milne
56f7dd7b3c First crack
Some checks failed
CI / scan_ruby (push) Has been cancelled
CI / scan_js (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
CI / system-test (push) Has been cancelled
2025-10-23 16:45:00 +11:00
Dan Milne
1ff0a95392 First commit
Some checks failed
CI / scan_ruby (push) Has been cancelled
CI / scan_js (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
CI / system-test (push) Has been cancelled
2025-10-23 16:19:56 +11:00