Skip to content

Jellyfin SSO with Authentik (OIDC)

Jellyfin uses the SSO-Auth plugin with OpenID Connect for true single sign-on with Authentik. This provides automatic login - no separate credentials needed.

Key Difference from arr-stack: Jellyfin supports native OIDC via plugin, so we use that instead of forward auth. This gives true SSO (one-click login) rather than just access control.

Architecture

User → jellyfin.bogocat.com → K8s Ingress
                            Jellyfin (LXC 113)
                        ┌──────────┴──────────┐
                        │                     │
                   (not logged in)      (logged in)
                        │                     │
                        ▼                     ▼
              Click "Sign in with SSO"   Access granted
               Redirect to Authentik
               Login (or auto if cached)
               Redirect back to Jellyfin
               (auto-creates user, sets admin based on groups)

Prerequisites

  • Authentik deployed in K8s (authentik namespace)
  • Jellyfin running (LXC 113: 10.89.97.97)
  • DNS: jellyfin.bogocat.com10.89.97.220
  • Tier groups configured in Authentik (tier-owner, tier-family, tier-friends)

Role-Based Access

Tier Group Jellyfin Role Access Level
tier-owner Admin Full admin access
tier-family User All libraries
tier-friends User All libraries
tier-guests (not configured) No access

Setup Guide

Step 1: Create OIDC Provider in Authentik

  1. Go to https://auth.bogocat.com → Providers → Create → OAuth2/OpenID Provider
  2. Configure:
Field Value
Name jellyfin
Authorization flow default-provider-authorization-implicit-consent
Redirect URI https://jellyfin.bogocat.com/sso/OID/redirect/authentik
  1. Note the Client ID and Client Secret

Step 2: Create Application in Authentik

  1. Applications → Create
  2. Configure:
Field Value
Name Jellyfin
Slug jellyfin
Provider jellyfin
Launch URL https://jellyfin.bogocat.com/sso/OID/start/authentik
  1. Policy / Group / User Bindings → Create Binding → Group
  2. Add: tier-owner, tier-family, tier-friends

Step 3: Create Groups Scope in Authentik

  1. Customization → Property Mappings → Create → Scope Mapping
  2. Configure:
Field Value
Name groups
Scope name groups
Expression return list(request.user.ak_groups.values_list("name", flat=True))
  1. Providers → jellyfin → Edit → Advanced Protocol Settings
  2. Add the groups scope to Scopes

Step 4: Install SSO-Auth Plugin in Jellyfin

  1. Login to Jellyfin as admin
  2. Dashboard → Plugins → Repositories → Add (+)
Field Value
Name SSO-Auth
URL https://raw.githubusercontent.com/9p4/jellyfin-plugin-sso/manifest-release/manifest.json
  1. Catalog → SSO-Auth → Install
  2. Restart Jellyfin:
    pct exec 113 -- systemctl restart jellyfin
    

Step 5: Configure SSO-Auth Plugin

  1. Dashboard → Plugins → SSO-Auth
  2. Configure:
Field Value
Name of OID Provider authentik
OID Endpoint https://auth.bogocat.com/application/o/jellyfin/
OpenID Client ID (from Authentik)
OID Secret (from Authentik)
Enabled
Enable Authorization by Plugin
Enable All Folders
Roles tier-owner
tier-family
tier-friends
Admin Roles tier-owner
Role Claim groups
Request Additional Scopes groups
  1. Save and restart Jellyfin

Step 6: Add SSO Login Button

  1. Dashboard → General → Login Disclaimer
  2. Add:
<form action="https://jellyfin.bogocat.com/sso/OID/start/authentik">
  <button class="raised block emby-button button-submit">
    Sign in with SSO
  </button>
</form>
  1. Save

Step 7: Create K8s Ingress

The ingress is a simple passthrough (no forward auth needed since Jellyfin handles OIDC itself):

# /root/tower-fleet/manifests/apps/jellyfin/ingress.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: jellyfin-external
  namespace: arr-stack
  labels:
    app.kubernetes.io/managed-by: tower-fleet
    app.kubernetes.io/name: jellyfin
spec:
  type: ClusterIP
  clusterIP: None
  ports:
    - name: http
      port: 8096
      targetPort: 8096
---
apiVersion: v1
kind: Endpoints
metadata:
  name: jellyfin-external
  namespace: arr-stack
subsets:
  - addresses:
      - ip: 10.89.97.97
    ports:
      - name: http
        port: 8096
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: jellyfin
  namespace: arr-stack
  labels:
    app.kubernetes.io/managed-by: tower-fleet
    app.kubernetes.io/name: jellyfin
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: HTTP
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - jellyfin.bogocat.com
      secretName: wildcard-bogocat-tls
  rules:
    - host: jellyfin.bogocat.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: jellyfin-external
                port:
                  number: 8096

Apply:

kubectl apply -f /root/tower-fleet/manifests/apps/jellyfin/ingress.yaml

Step 8: Test

  1. Open incognito browser
  2. Go to https://jellyfin.bogocat.com
  3. Click "Sign in with SSO"
  4. Authenticate with Authentik (or auto-login if session exists)
  5. Redirected back to Jellyfin, logged in automatically
  6. If user is in tier-owner, they have admin privileges

Troubleshooting

"Client ID Error" on redirect

  • Verify Client ID in Jellyfin matches Authentik provider exactly
  • Check for extra spaces or wrong ID

"Permission denied" after Authentik login

  • User not in a group bound to the application
  • Add user to tier-owner, tier-family, or tier-friends

User created but not admin

  • Check Admin Roles includes tier-owner
  • Check Role Claim is set to groups
  • Check Request Additional Scopes includes groups
  • Verify groups scope is added to provider in Authentik

"Error processing request" / endpoint error

  • Enable "Do not validate endpoints" in plugin settings
  • Check OID Endpoint URL ends with /

LDAP vs OIDC

Jellyfin previously used LDAP authentication. Here's why we switched:

Feature LDAP OIDC (SSO Plugin)
Auto-login ❌ Must type credentials ✅ One-click if Authentik session exists
Role-based admin ❌ Manual configuration ✅ Automatic via groups claim
User creation ✅ Automatic ✅ Automatic
Session sharing ❌ Separate session ✅ Shares Authentik session

The LDAP provider can be disabled in Jellyfin plugins if no longer needed.

Files Reference

File Purpose
/root/tower-fleet/manifests/apps/jellyfin/ingress.yaml K8s ingress (passthrough)
/root/tower-fleet/docs/infrastructure/jellyfin-sso.md This documentation