feat: configuration form, sign-in page and provider test #10

Merged
ryan.mcgee merged 5 commits from feat/config-ui into main 2026-10-17 01:59:20 +00:00
Owner

Summary

  • Replace the JSON textarea with a real configuration form, add an admin-only provider test and a public sign-in page, and fix a bug that made SSO fail for most real browsers.

Changes

  • Form editor (configPage.html): one card per provider with labelled fields and help text, live redirect URI and sign-in address with copy buttons, masked client secret (keep, replace or remove), comma-separated roles, validation before save, per-provider Test provider. Reads and writes the same stored configuration, so existing installs open unchanged and user links are kept.
  • GET /sso/oidc/login: public sign-in page listing the usable providers (redirects when there is exactly one). Names are HTML-encoded; stylesheet is nonce'd.
  • POST /sso/oidc/admin/test (administrators only): uncached discovery fetch and secret check; reports errors and warnings, never the secret.
  • Bug fix: the login-code exchange rejected device ids longer than 128 characters. jellyfin-web stores base64(user agent|timestamp), about 168 characters, so every SSO sign-in failed ("Sign-in failed") for any browser that had used Jellyfin before. The limit now matches Jellyfin's 256-character DeviceId column. This affects the released 1.0.0 and 1.1.0.
  • README, smoke.sh (landing page, test endpoint, browser-length device ids).

Verification

  • 81 unit tests (was 43). New tests were mutation-checked: removing HTML encoding, inverting the S256 warning and restoring the 128 limit each make tests fail.
  • scripts/smoke.sh: all checks pass, exit 0. Against a copy with the old 128 limit it fails 5 checks, so the new device-id coverage would have caught the bug.
  • All CI steps run in a fresh SDK container: build 0 warnings, format clean, tests, shellcheck, package, manifest.
  • Real Jellyfin 10.11.11 plus mock IdP, driven in headless Chromium: legacy config opens in the form; validation blocks bad input without touching stored config; an unchanged save keeps secret, user link and every field; adding a provider with messy roles saves clean data; secret to secret-file switch; Test provider (ok and unreachable); landing page with two providers and the single-provider redirect; full SSO login from the UI-built config in a browser that already held a 168-character device id; the Branding disclaimer link on the real login page.

Not covered

  • The form is verified by hand, not in CI (no browser in CI).
  • This is a feature: version stays 1.1.0 here; bump to 1.2.0 in a separate PR when releasing.
## Summary - Replace the JSON textarea with a real configuration form, add an admin-only provider test and a public sign-in page, and fix a bug that made SSO fail for most real browsers. ## Changes - **Form editor** (`configPage.html`): one card per provider with labelled fields and help text, live redirect URI and sign-in address with copy buttons, masked client secret (keep, replace or remove), comma-separated roles, validation before save, per-provider **Test provider**. Reads and writes the same stored configuration, so existing installs open unchanged and user links are kept. - **`GET /sso/oidc/login`**: public sign-in page listing the usable providers (redirects when there is exactly one). Names are HTML-encoded; stylesheet is nonce'd. - **`POST /sso/oidc/admin/test`** (administrators only): uncached discovery fetch and secret check; reports errors and warnings, never the secret. - **Bug fix**: the login-code exchange rejected device ids longer than 128 characters. jellyfin-web stores base64(user agent|timestamp), about 168 characters, so every SSO sign-in failed ("Sign-in failed") for any browser that had used Jellyfin before. The limit now matches Jellyfin's 256-character `DeviceId` column. **This affects the released 1.0.0 and 1.1.0.** - README, `smoke.sh` (landing page, test endpoint, browser-length device ids). ## Verification - 81 unit tests (was 43). New tests were mutation-checked: removing HTML encoding, inverting the S256 warning and restoring the 128 limit each make tests fail. - `scripts/smoke.sh`: all checks pass, exit 0. Against a copy with the old 128 limit it fails 5 checks, so the new device-id coverage would have caught the bug. - All CI steps run in a fresh SDK container: build 0 warnings, format clean, tests, shellcheck, package, manifest. - Real Jellyfin 10.11.11 plus mock IdP, driven in headless Chromium: legacy config opens in the form; validation blocks bad input without touching stored config; an unchanged save keeps secret, user link and every field; adding a provider with messy roles saves clean data; secret to secret-file switch; Test provider (ok and unreachable); landing page with two providers and the single-provider redirect; full SSO login from the UI-built config in a browser that already held a 168-character device id; the Branding disclaimer link on the real login page. ## Not covered - The form is verified by hand, not in CI (no browser in CI). - This is a feature: version stays 1.1.0 here; bump to 1.2.0 in a separate PR when releasing.
- GET /sso/oidc/login lists usable providers (redirects when there
  is exactly one); names are HTML-encoded, CSP nonce on the stylesheet
- POST /sso/oidc/admin/test (administrators only) does an uncached
  discovery fetch and secret check and reports errors and warnings
- share the provider usability rule between login and landing page
- one card per provider with labelled fields and help text
- live redirect URI and sign-in address with copy buttons
- masked client secret with keep, replace and remove
- comma-separated role lists, validation before save, and a test button
- preserve fields and user links the page does not edit
- show signing keys and PKCE only when discovery succeeded
- style the read-only address boxes for dark and light themes
- jellyfin-web stores base64(user agent|timestamp) as its device id,
  routinely 160+ characters, and the 128 limit made every SSO sign-in
  fail for browsers that had used Jellyfin before
- the limit now matches Jellyfin's DeviceId column and is unit tested
docs: document the form, sign-in page and extended smoke test
All checks were successful
CI / verify (pull_request) Successful in 54s
7cfd636b9d
- describe the provider form, Test provider and the sign-in address
- document the login page link and Jellyfin's new-tab behaviour
- smoke test covers the landing page, the admin-only test endpoint and
  browser-length device ids
ryan.mcgee deleted branch feat/config-ui 2026-10-17 01:59:20 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Enclave-Information-Systems/jellyfin-sso-plugin!10
No description provided.