feat: harden secrets and add regression and smoke tests #2

Merged
ryan.mcgee merged 3 commits from fix/open-items into main 2026-10-16 22:00:35 +00:00
Owner

Summary

  • Closes the open items from the initial plugin PR: plain-text client secret, untested password-overwrite fix, and the unchecked jellyfin-web credential format.

Changes

  • ClientSecretFile: read the client secret from a file on every use (rotation needs no restart). Setting both sources or an empty file is rejected, and a broken config now fails at start, before the IdP login. With no secret configured the token request omits client_secret (PKCE-only public client). Inline ClientSecret still works.
  • Regression test for the created-user empty-password bug: a fake IUserManager copies Jellyfin 10.11.11 persistence (fresh entity per read, UpdateUserAsync overwrites the stored password). Also covers link, collision, disabled, role and auto-create cases.
  • scripts/smoke.sh: end-to-end run against pinned Jellyfin and a mock IdP, including a check that jellyfin-web still references the jellyfin_credentials keys the callback page writes. README documents running it before supporting a new server version.

Verification

  • dotnet build -warnaserror: 0 warnings, 0 errors; dotnet format --verify-no-changes clean.
  • dotnet test: 43 passed, 0 failed (was 24).
  • Regression test fails (2 cases) with the old ChangePassword/UpdateUserAsync order temporarily restored, passes with the fix.
  • scripts/smoke.sh: all checks pass, exit 0 (shellcheck v0.10.0 clean).
## Summary - Closes the open items from the initial plugin PR: plain-text client secret, untested password-overwrite fix, and the unchecked jellyfin-web credential format. ## Changes - `ClientSecretFile`: read the client secret from a file on every use (rotation needs no restart). Setting both sources or an empty file is rejected, and a broken config now fails at `start`, before the IdP login. With no secret configured the token request omits `client_secret` (PKCE-only public client). Inline `ClientSecret` still works. - Regression test for the created-user empty-password bug: a fake `IUserManager` copies Jellyfin 10.11.11 persistence (fresh entity per read, `UpdateUserAsync` overwrites the stored password). Also covers link, collision, disabled, role and auto-create cases. - `scripts/smoke.sh`: end-to-end run against pinned Jellyfin and a mock IdP, including a check that jellyfin-web still references the `jellyfin_credentials` keys the callback page writes. README documents running it before supporting a new server version. ## Verification - dotnet build -warnaserror: 0 warnings, 0 errors; dotnet format --verify-no-changes clean. - dotnet test: 43 passed, 0 failed (was 24). - Regression test fails (2 cases) with the old ChangePassword/UpdateUserAsync order temporarily restored, passes with the fix. - scripts/smoke.sh: all checks pass, exit 0 (shellcheck v0.10.0 clean).
- add ClientSecretFile, read on every use so rotation needs no restart
- reject setting both secret sources or an empty secret file
- omit client_secret when none is configured (PKCE-only public client)
- fail at start, before the IdP login, on broken secret config
- fake IUserManager copies Jellyfin 10.11.11 persistence: reads return
  fresh entities and UpdateUserAsync overwrites the stored password
- regression for the created-user empty-password bug; fails with the
  old call order and passes with the fix
- link, collision, disabled, role and auto-create cases
- build the plugin and run it against pinned Jellyfin and a mock IdP
  in a throwaway podman pod
- cover sign-in, role and admin mapping, replay, CSRF, refusals and
  secret-file handling
- fail when jellyfin-web stops referencing the credential keys the
  callback page writes
- document running it before supporting a new server version
ryan.mcgee deleted branch fix/open-items 2026-10-16 22:00:35 +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!2
No description provided.