Repository navigation
[Feature] Managed accounts and server-side PIN #328
Copy link
Copy link
Open
Labels
Description
What problem does this solve?
Families sharing one TV have no way to say "these accounts belong together", and the PIN
the clients offer is stored per device:
- Every client's sign-in PIN is local to the device. A PIN set on one TV does nothing on
another, and the clients can't offer "admins must have a PIN" in any enforceable way. - The stored value is an unsalted SHA-256 of a 4-digit PIN, and the client-side lockout
is reset by clearing app data. The plugin has no PIN storage or route today. - The user picker shows every public user on the server. On a server hosting more than one
family, each TV shows everyone.
Proposed solution
All of it is additive and optional. Clients keep working unchanged without it, and the
clients must stay fully usable when the plugin is absent or unreachable.
- Managed accounts. Each user gets a
managedBylist of administrator user IDs, stored
in the plugin configuration. It is a list so a child with parents in separate homes can
be managed by both.PUT /Moonfin/Users/{id}/ManagedBy(admin) sets the list.GET /Moonfin/Managed(any signed-in user) returns the users the caller manages as
{id, name, imageTag}, so a client can filter its user picker.- A "Managed by" picker per user on the existing plugin config page.
- Server-side PIN. The plugin stores a salted, slow hash per user and verifies it, so
clients stop comparing hashes and can't be defeated by reading the synced value.GET /Moonfin/Pinreturns{ enabled }only, never a hash. PINs are exactly 4 digits,
matching what the clients accept today.PUT /Moonfin/Pinsets or changes it (requires the current PIN when one exists).POST /Moonfin/Pin/Verifychecks an entry, with server-side rate limiting and lockout.DELETE /Moonfin/Pinremoves it (current PIN, or an admin).- An admin-reset path for forgotten PINs.
- The config page lists administrators who have no PIN, so setting one doesn't depend
on a client prompt. Clients only prompt when no server-side PIN is available.
Settings stay additive: new properties are nullable and typed the way clients send them,
per the settings-profile rule in CONTRIBUTING.
Area
Admin defaults / config page
Server
Jellyfin
Client impact
Needs matching client work in Moonfin-Core (Moonfin-Client/Moonfin-Core#1912), Smart-TV (Moonfin-Client/Smart-TV#541) and Roku (Moonfin-Client/Roku#310). Clients keep working without the plugin.
Alternatives considered
- Sync the hash through the existing settings profile. Needs every client to produce
the identical hash, which is hard with a salted scheme across four toolchains, and still
leaves the hash readable. - Named household groups. More to build and name, with no benefit over a managed-by list.
Additional context
- Companion client proposals: Moonfin-Core [Feature] Family features: admin PIN, QR approval, managed accounts, time limits Moonfin-Core#1912, Smart-TV [Feature] Family features: server-backed PIN, QR approval, managed accounts, time limits Smart-TV#541, Roku [Feature] Family features: server-backed PIN, managed accounts, time limits Roku#310.
- Clients detect the plugin with
/Moonfin/Pingand fall back to today's local behavior.
If the plugin is unreachable at the PIN gate they fall back to a locally cached verifier
rather than locking the family out (fail-open, by design). - Migration: when a plugin appears for a device with a local PIN, the next successful local
verify uploads what the user typed, since the client only holds a hash. - Emby is not changed. All new code lives under
Jellyfin/. I won't touchshared/
orEmby/, because the Emby project compilesshared/*.csand I have no Emby server to
test on. Clients must treat these routes as absent on Emby (they already degrade when
the plugin lacks a feature). If you want Emby parity later, that is a separate change
that needs someone with an Emby server to test. - I'll build and maintain both parts, as separate PRs (managed accounts, PIN)
once the shape is OK, and I'll run the Jellyfin and Emby test projects to confirm
nothing regressed. - I used an AI assistant (Claude) to help research and draft this proposal and will say so
on any PR. I'm the one who will build, test (against my own Jellyfin server) and answer for the change.
Reactions are currently unavailable
Activity
github-actions commentedon Oct 18, 2026
Thanks for the report, @benklop.
Before anyone can pick this up it needs a little more from you, so it has been labelled Missing Template.
This issue skipped the issue form
It was opened without one of the forms, so the fields that say which version, platform and setup this involves are all missing.
The forms also decide how an issue gets labelled and routed. Skipping the form means nobody was prompted for the one thing the report actually needs.
Please open a fresh one from New issue and pick the form that fits, then this can be closed as a duplicate. If you would rather not start over, paste the form's answers into a comment below and they will be picked up.
Each label comes off automatically once that piece is sorted.
benklop commentedon Oct 18, 2026
@RadicalMuffinMan I have a handful of features I had built on the previous android TV app and have been using on my own fork for a while. I'd like to get back to using vanilla moonfin, so i'm working on porting them to the new client apps and server plugin. For the plugin itself there are only 2 things: