Ship a Jellyfin client that is already signed in. An administrator asks the server for a session on behalf of an existing user and gets back that user's normal access token.
Jellyfin issues the session, lists it beside every other client, and revokes it the usual way. The plugin only asks.
Requires Jellyfin 12.0.0. Add this repository under Dashboard > Plugins > Repositories, install Session Provisioning from the catalog, and restart.
https://raw.githubusercontent.com/voc0der/jellyfin-plugin-session-provisioning/main/manifest.json
Note
Full repository of this author's plugins: voc0der/jellyfin-plugins.
- Download the ZIP from the releases page
- Extract it into
<jellyfin-data>/plugins/ - Restart Jellyfin
./build.shRuns the tests and writes the archive to artifacts/.
This plugin is stateless and does not use a settings page. To provision, generate a secret and its SHA256 hash on a trusted machine:
SECRET="$(openssl rand -base64 32 | tr '+/' '-_' | tr -d '=')"
HASH="$(printf '%s' "$SECRET" | sha256sum | awk '{print $1}')"
printf 'Provisioning secret (keep for client): %s\n' "$SECRET"
printf 'Provisioning hash (give Jellyfin): %s\n' "$HASH"Give the hash to Jellyfin, keep the secret for whatever does your provisioning:
services:
jellyfin:
environment:
SESSION_PROVISIONING_SECRET_HASH_FILE: /run/secrets/sp-hash
volumes:
- ./sp-hash:/run/secrets/sp-hash:roUntil a valid hash is configured, the endpoint mints nothing. SESSION_PROVISIONING_SECRET_HASH passes the hash directly if you would rather not mount a file.
Block /SessionProvisioning/* at your public reverse proxy. Nothing outside your network should reach it.
curl -X POST "$JELLYFIN_URL/SessionProvisioning/Mint" \
-H "Authorization: MediaBrowser Token=\"$JELLYFIN_API_KEY\"" \
-H "X-Session-Provisioning-Secret: $SECRET" \
-H 'Content-Type: application/json' \
-d '{
"userId": "24a848abe3474a4a90d863fb808eca9c",
"deviceId": "living-room-mpv-shim-0f2a",
"deviceName": "Living Room MPV Shim",
"appVersion": "3.0.0"
}'{
"userId": "24a848abe3474a4a90d863fb808eca9c",
"deviceId": "living-room-mpv-shim-0f2a",
"deviceName": "Living Room MPV Shim",
"accessToken": "..."
}The token comes back once. It is an ordinary session token carrying that user or administrator's own permissions.
Tokens are tied to a deviceId. Re-minting for the same ID replaces the existing token. Manage or revoke devices via the dashboard.
- Two credentials are required, always. Jellyfin administrator authorization and the provisioning secret.
- Turning it off: remove the hash and the next request is refused, no restart needed. Disabling the plugin refuses immediately too.
- Rate limited to 120 requests a minute, and one mint runs at a time.
- If the target user is at their session limit, minting is refused and their existing token keeps working. Revoke the old device first.
docs/ARCHITECTURE.md covers the design and the Jellyfin behaviour it depends on, verified against 10.11.11 with the package-level surface re-checked on 12.0.0. docs/SECURITY.md covers the threat model and the invariants. docs/TESTING.md covers reproducing any of it.