Files
jellyfinsso/README.md
Pascal Linxweiler 7dc79bf003 fix: admin role mapping grants only, revoke behind opt-in
SSO login for an existing admin whose token lacked the admin role was
silently demoting the account, locking admins out of the dashboard.
Missing admin role now leaves the flag alone unless
RevokeAdminWithoutRole is enabled.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 14:44:07 +02:00

93 lines
4.3 KiB
Markdown

# Jellyfin OIDC Auth Plugin
Log in to Jellyfin with any OpenID Connect provider (Authelia, Authentik, Keycloak, Pocket ID, Google, ...).
## How it works
1. User opens `https://<jellyfin>/OidcAuth/login`.
2. Plugin redirects to your provider (authorization code flow + PKCE via `IdentityModel.OidcClient`).
3. Provider redirects back to `https://<jellyfin>/OidcAuth/callback`; the plugin exchanges the code, validates the tokens, and maps claims to a Jellyfin user (creating it if configured).
4. A small callback page creates a Jellyfin session (`ISessionManager.AuthenticateDirect`), writes the credentials into the web client's local storage, and redirects to `/web/`.
## Build
```bash
dotnet publish Jellyfin.Plugin.OidcAuth --configuration Release --output artifacts
```
## Install via plugin repository (recommended)
1. In Jellyfin: Dashboard → Plugins → Repositories → **+**
2. Repository URL:
```
https://git.linxweiler.xyz/pascallinxweiler/jellyfinplugin/raw/branch/main/manifest.json
```
3. Catalog → Authentication → **OIDC Auth** → Install → restart Jellyfin.
Updates show up in the catalog automatically when a new version is added to `manifest.json`.
## Install manually
Copy these files from `artifacts/` into a new folder in Jellyfin's plugin directory
(e.g. `config/plugins/OidcAuth/`), then restart Jellyfin:
- `Jellyfin.Plugin.OidcAuth.dll`
- `IdentityModel.OidcClient.dll`
- `IdentityModel.dll`
Requires Jellyfin 10.11.x.
## Configure
At your OIDC provider, create a **confidential web client** with redirect URI:
```
https://<jellyfin>/OidcAuth/callback
```
Then in Jellyfin: Dashboard → Plugins → OIDC Auth:
| Setting | Meaning |
|---|---|
| Issuer URL | Provider base URL; discovery doc must exist at `<issuer>/.well-known/openid-configuration` |
| Client ID / Secret | From your provider |
| Scopes | Default `openid profile email`; add `groups` if roles come via that scope |
| Username claim | Default `preferred_username`, falls back to `sub` |
| Role claim | Default `groups` |
| Allowed roles | CSV; empty = every authenticated user may log in |
| Admin roles | CSV; users with one of these roles are granted admin on SSO login. Missing role does **not** revoke admin unless "Also revoke admin" is enabled. Empty = plugin never touches the admin flag |
| Create users on first login | On by default; new users get access to all libraries |
| Set random password for auto-created users | On by default. Without it, Jellyfin accepts a **blank password** for these users from any client — convenient on a LAN-only server, dangerous on an exposed one |
| Disable strict endpoint validation | Enable for Google and other providers whose endpoints are on a different host than the issuer |
## Login button on the web login page
Jellyfin does not let plugins modify the login page. Add a button via
Dashboard → General → Branding → Login disclaimer:
```html
<a is="emby-linkbutton" class="raised block emby-button" href="/OidcAuth/login">Sign in with SSO</a>
```
## TV and native clients
The plugin does not change or disable Jellyfin's normal password login, so TV apps
(Android TV, Roku, Swiftfin, Kodi, ...) keep working exactly as before. For users
that exist only through OIDC, three options:
1. **Quick Connect** (recommended): enable it in Dashboard → General. On the TV choose
Quick Connect, then approve the code from the web client (where you're logged in via OIDC).
2. **Set a password**: after the first OIDC login, the user sets a password in their
web profile and uses that on the TV.
3. **Blank password** (LAN-only setups): turn off "Set random password for auto-created
users" — TV login then works with username + empty password. Do **not** do this on a
server reachable from the internet.
## Notes / limitations
- The OIDC browser flow itself works for the **web client** (and anything that can open a browser and reuse the resulting session token). Native clients that only show the username/password form can't use this flow directly — see the TV section above.
- Behind a reverse proxy, make sure Jellyfin sees the external scheme/host (`X-Forwarded-Proto`, `X-Forwarded-Host` — Jellyfin's "Known proxies" setting), otherwise the computed redirect URI won't match the one registered at the provider.
- Password login stays enabled; this plugin adds an additional login path.