Add Authentik SSO integration for Jellyfin (#239)

## Summary
- Add Authentik OIDC provider + application for Jellyfin via blueprint (all authenticated users allowed, no policy binding)
- Wire `jellyfin-client-secret` through ExternalSecret and Authentik worker deployment
- Install [jellyfin-plugin-sso](https://github.com/9p4/jellyfin-plugin-sso) v4.0.0.3 via Ansible, with OIDC config template
- Authentik `admins` group maps to Jellyfin administrator role
- Local login left enabled; SSO is additive

## Deployment and Testing
- [ ] Sync ArgoCD `authentik` app on branch — verify provider + application appear in Authentik admin
- [ ] `mise run provision-indri -- --tags jellyfin --check --diff` (dry run)
- [ ] `mise run provision-indri -- --tags jellyfin` (deploy plugin + config)
- [ ] Test SSO flow: `https://jellyfin.ops.eblu.me/sso/OID/start/authentik`
- [ ] Verify `eblume` account auto-links via `preferred_username` match
- [ ] Verify admins group → Jellyfin admin
- [ ] Reset ArgoCD app revision to main after merge

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Reviewed-on: https://forge.ops.eblu.me/eblume/blumeops/pulls/239
This commit is contained in:
Erich Blume 2026-02-21 20:05:44 -08:00
commit 07fb48626d
8 changed files with 142 additions and 0 deletions

View file

@ -245,3 +245,45 @@ data:
enabled: true
negate: false
timeout: 30
jellyfin.yaml: |
version: 1
metadata:
name: BlumeOps Jellyfin SSO
labels:
blueprints.goauthentik.io/description: "Jellyfin OIDC provider and application"
entries:
# OAuth2 provider for Jellyfin
- model: authentik_providers_oauth2.oauth2provider
id: jellyfin-provider
identifiers:
name: Jellyfin
attrs:
name: Jellyfin
authorization_flow: !Find [authentik_flows.flow, [slug, default-provider-authorization-implicit-consent]]
invalidation_flow: !Find [authentik_flows.flow, [slug, default-provider-invalidation-flow]]
client_type: confidential
client_id: jellyfin
client_secret: !Env AUTHENTIK_JELLYFIN_CLIENT_SECRET
redirect_uris:
- matching_mode: strict
url: https://jellyfin.ops.eblu.me/sso/OID/redirect/authentik
signing_key: !Find [authentik_crypto.certificatekeypair, [name, authentik Self-signed Certificate]]
property_mappings:
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, openid]]
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, email]]
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, profile]]
sub_mode: hashed_user_id
include_claims_in_id_token: true
# Jellyfin application — all authenticated users allowed (no policy binding)
- model: authentik_core.application
id: jellyfin-app
identifiers:
slug: jellyfin
attrs:
name: Jellyfin
slug: jellyfin
provider: !KeyOf jellyfin-provider
meta_launch_url: https://jellyfin.ops.eblu.me
policy_engine_mode: all

View file

@ -68,6 +68,11 @@ spec:
secretKeyRef:
name: authentik-config
key: zot-client-secret
- name: AUTHENTIK_JELLYFIN_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: authentik-config
key: jellyfin-client-secret
volumeMounts:
- name: blueprints
mountPath: /blueprints/custom

View file

@ -49,3 +49,7 @@ spec:
remoteRef:
key: "Authentik (blumeops)"
property: zot-client-secret
- secretKey: jellyfin-client-secret
remoteRef:
key: "Authentik (blumeops)"
property: jellyfin-client-secret