feat: initial Jellyfin OIDC auth plugin
OpenID Connect SSO for Jellyfin 10.10 (net8.0). Authorization code flow with PKCE via IdentityModel.OidcClient, automatic user creation with random password, role based admin/access mapping, plugin repo manifest. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
92
README.md
Normal file
92
README.md
Normal file
@@ -0,0 +1,92 @@
|
||||
# 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://raw.githubusercontent.com/YOUR_GITHUB_USER/jellyfinoidc/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.10.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; 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.
|
||||
Reference in New Issue
Block a user