--- title: "Setting Up Jellyfin SSO with Authentik: Surviving the Beta" date: 2025-12-28 draft: false --- I recently integrated Jellyfin with Authentik for Single Sign-On (SSO). While the plugin works, it is still very much in an early development phase. The logging is often sparse or cryptic, and the feedback loop can be frustrating. Here is a guide focused on the obscure errors you might encounter and the simple fixes that aren't immediately obvious. ## The Setup The configuration is best handled via API (curl) rather than the UI, as it ensures all fields are correctly typed and persistent. ### 1. Authentik (Terraform) Let Authentik manage the secrets. Don't hardcode them. ```hcl resource "authentik_provider_oauth2" "jellyfin" { name = "Jellyfin" client_id = "jellyfin-ericxliu-me" # client_secret omitted -> auto-generated property_mappings = [ authentik_scope_mapping.openid.id, authentik_scope_mapping.profile.id, authentik_scope_mapping.email.id, authentik_scope_mapping.groups.id ] # ... } ``` ### 2. Jellyfin Plugin (Bash/Curl) ```bash # ... (retrieve secret from terraform) ... curl -X POST "https://jellyfin.ericxliu.me/SSO/OID/Add/authentik" ... -d '{ "OidClientId": "jellyfin-ericxliu-me", "OidSecret": "'"${SECRET}"'", "OidScopes": ["openid", "profile", "email", "groups"], "SchemeOverride": "https", "RoleClaim": "groups" }' ``` ## Obscure Errors & Fixes Because the plugin is still maturing, it doesn't always handle configuration errors gracefully. Here are the two main "cryptic" failures I encountered. ### 1. The "Value cannot be null" Crash **The Symptom**: You attempt to start the SSO flow and get a generic 500 error. The Jellyfin logs show a C# exception: ``` System.ArgumentNullException: Value cannot be null. (Parameter 'source') at System.Linq.Enumerable.Prepend[TSource](IEnumerable`1 source, TSource element) at Jellyfin.Plugin.SSO.Api.SSOController.OidChallenge(...) ``` **The Reality**: This looks like deep internal failure, but it's actually a simple configuration miss. The plugin code attempts to prepend "openid profile" to your configured scopes without checking if your scopes array exists first. **The Fix**: You **must** explicitly provide `"OidScopes"` in your JSON configuration. It cannot be null or omitted. ```json "OidScopes": ["openid", "profile", "email", "groups"] ``` ### 2. The HTTP/HTTPS Mismatch (Redirect Loop) **The Symptom**: Authentik rejects the authorization request with "Redirect URI mismatch", or the browser enters a redirect loop. **The Reality**: Jellyfin often sits behind a reverse proxy (Ingress/Traefik) terminating TLS. Use `Browser Developer Tools` to inspect the network requests. You will likely see the `redirect_uri` parameter encoded as `http://jellyfin...` instead of `https://`. configuration. **The Fix**: Do not rely on header forwarding magic. Force the scheme in the plugin configuration: ```json "SchemeOverride": "https" ``` ### 3. Case Sensitivity in JSON **The Symptom**: Configuration seems to be ignored or fields remain empty after a POST. **The Reality**: The plugin's API controller keys are Case Sensitive in some versions/contexts. **The Fix**: Stick to PascalCase for the keys (`OidEndpoint`, `AdminRoles`) as seen in the C# DTOs, rather than camelCase (`oidEndpoint`), unless the specific version documentation explicitly states otherwise. When in doubt, checking the source code (`SSOController.cs`) is often faster than trusting the README. ## Summary When debugging Jellyfin SSO, don't trust the UI to tell you what's wrong. 1. **Check the logs** (`kubectl logs`) for C# stack traces. 2. **Sanitize your JSON** inputs (arrays can't be null). 3. **Inspect the URL parameters** in your browser to see what Redirect URI is actually being generated. ### References - Jellyfin SSO Plugin Repository: `https://github.com/9p4/jellyfin-plugin-sso` - Authentik Documentation: `https://goauthentik.io/docs/providers/oauth2/` - Jellyfin API Documentation: `https://api.jellyfin.org/`