📚 Auto-publish: Add/update 1 blog posts
All checks were successful
Hugo Publish CI / build-and-deploy (push) Successful in 53s
All checks were successful
Hugo Publish CI / build-and-deploy (push) Successful in 53s
Generated on: Sun Dec 28 20:42:03 UTC 2025 Source: md-personal repository
This commit is contained in:
85
content/posts/jellyfin-sso-with-authentik.md
Normal file
85
content/posts/jellyfin-sso-with-authentik.md
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
---
|
||||||
|
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/`
|
||||||
Reference in New Issue
Block a user