Skip to content

🔐 Connecter un service à Authentik en SSO (OIDC)

Procédure compagnon des guides d'installation LXC : elle suppose que le service à connecter (Jellyfin, Teleport ou FileBrowser Quantum) et Authentik sont déjà installés et fonctionnels.

Le point de départ côté Authentik est toujours le même — créer un provider OAuth2/OpenID puis une application qui l'expose — mais l'intégration côté service diffère fortement : plugin à installer manuellement pour l'un, connecteur natif pour un autre. Chaque section ci-dessous est autonome.

Service Méthode d'intégration Redirect URI Guide d'installation
Jellyfin Plugin communautaire (installation manuelle) /sso/OID/r/<nom> Installer Jellyfin
Teleport Connecteur natif (tctl create) /v1/webapi/oidc/callback Installer Teleport
FileBrowser Quantum Configuration native (config.yaml) /api/auth/oidc/callback Installer FileBrowser

Dans les trois cas, l'endpoint OIDC exposé par Authentik suit le même format : https://auth.votre-domaine.tld/application/o/<slug-application>/.


Jellyfin — plugin SSO-Auth

L'intégration repose sur le plugin communautaire jellyfin-plugin-sso (9p4). Ce plugin n'est pas distribué dans le catalogue officiel Jellyfin (https://repo.jellyfin.org/files/plugin/manifest.json ne le liste pas) : il ne peut donc pas s'installer depuis Tableau de bord → Plugins → Catalogue, l'installation se fait manuellement.

Nom de provider utilisé dans les exemples ci-dessous : authentik.

1. Créer le provider et l'application dans Authentik

Côté Authentik (Applications → Providers → Create), créer un provider OAuth2/OpenID :

Champ Valeur
Nom Jellyfin
Authorization flow default-provider-authorization-implicit-consent (ou équivalent)
Client type Confidential
Client ID jellyfin
Client Secret généré (openssl rand -hex 32), à conserver pour l'étape 3
Redirect URIs (strict) https://jellyfin.votre-domaine.tld/sso/OID/r/authentik
Scopes openid, email, profile
Signing key un certificat existant (ex : certificat auto-signé Authentik)

Le chemin de redirection compte : /r/, pas /p/

Le plugin expose deux routes distinctes par provider : /sso/OID/p/<nom> (lien de connexion, à utiliser dans le bouton SSO) et /sso/OID/r/<nom> (callback OAuth, à déclarer comme redirect_uri côté Authentik). Les confondre casse le flux d'authentification silencieusement (redirection vers la mauvaise route).

Puis créer l'Application correspondante (Applications → Applications → Create), avec un slugjellyfin dans cet exemple — qui détermine l'URL de l'endpoint OIDC exposé par Authentik : https://auth.votre-domaine.tld/application/o/<slug>/.

2. Installer le plugin manuellement

SSO_PLUGIN_VERSION="4.0.0.4"   # vérifier la dernière version sur la page Releases du plugin
PLUGIN_DEST="/var/lib/jellyfin/plugins/SSO-Auth_${SSO_PLUGIN_VERSION}"

pct exec 205 -- bash -c "
    apt-get install -y -qq unzip
    mkdir -p '${PLUGIN_DEST}'
    cd /tmp
    wget -q -O sso-plugin.zip \
        'https://github.com/9p4/jellyfin-plugin-sso/releases/download/v${SSO_PLUGIN_VERSION}/sso-authentication_${SSO_PLUGIN_VERSION}.zip'
    unzip -q sso-plugin.zip -d '${PLUGIN_DEST}'
    chown -R jellyfin:jellyfin '${PLUGIN_DEST}'
    rm -f sso-plugin.zip
"
pct exec 205 -- systemctl restart jellyfin

(remplacer 205 par l'ID réel du conteneur Jellyfin)

3. Configurer le provider dans le plugin

La configuration du plugin n'est pas exposée par une page dédiée dans l'UI standard — elle se fait via l'API du plugin lui-même, après authentification avec un compte admin Jellyfin existant :

JELLYFIN_BASE="http://localhost:8096"

TOKEN=$(curl -s -X POST "${JELLYFIN_BASE}/Users/AuthenticateByName" \
    -H "Content-Type: application/json" \
    -H 'X-Emby-Authorization: MediaBrowser Client="Setup", Device="Script", DeviceId="setup-oidc", Version="1.0.0"' \
    -d '{"Username":"admin","Pw":"<mot-de-passe-admin>"}' \
    | python3 -c "import sys,json; print(json.load(sys.stdin)['AccessToken'])")

curl -s -X POST "${JELLYFIN_BASE}/sso/OID/Add/authentik" \
    -H "Authorization: MediaBrowser Token=${TOKEN}" \
    -H "Content-Type: application/json" \
    -d '{
      "oidEndpoint": "https://auth.votre-domaine.tld/application/o/jellyfin/",
      "oidClientId": "jellyfin",
      "oidSecret": "<client-secret-authentik>",
      "enabled": true,
      "enableAuthorization": true,
      "enableAllFolders": true,
      "enabledFolders": [],
      "roles": [],
      "adminRoles": [],
      "roleClaim": "groups",
      "adminRoleClaim": "groups",
      "defaultProvider": false,
      "schemeOverride": "https",
      "overrideMethod": "",
      "oidScopes": ["profile", "email"]
    }'

Patch manuel obligatoire après l'appel API

Sur la version 4.0.0.4 du plugin, l'appel POST /sso/OID/Add/<nom> n'enregistre pas le provider dans la liste active (OidProviderNames) — c'est un comportement observé, pas documenté. Sans cette étape, le provider reste configuré mais invisible/inactif côté Jellyfin. Il faut l'ajouter à la main dans /var/lib/jellyfin/plugins/configurations/SSO-Auth.xml, juste avant la fermeture </PluginConfiguration> :

<OidProviderNames>
  <string>authentik</string>
</OidProviderNames>
<SamlProviderNames />

Puis redémarrer Jellyfin : pct exec 205 -- systemctl restart jellyfin.

À vérifier également selon la version du plugin utilisée : le nom de certains champs a changé entre versions (ex : RequestAdditionalScopes renommé en OidScopes) — en cas de config qui ne "prend" pas silencieusement, comparer les noms de balises réellement écrits dans le XML avec ceux attendus par la version installée.

Une fois ces deux étapes faites, une connexion SSO réussie crée automatiquement un utilisateur Jellyfin lié à l'identité Authentik via un CanonicalLink (mapping nom d'utilisateur → GUID Jellyfin) visible dans le même fichier XML.

4. Bouton SSO sur la page de connexion

Jellyfin permet d'injecter du contenu personnalisé sur l'écran de connexion via LoginDisclaimer (Tableau de bord → Général → Bannière de connexion), qui accepte du HTML :

curl -s -X POST "${JELLYFIN_BASE}/System/Configuration/branding" \
    -H "Authorization: MediaBrowser Token=${TOKEN}" \
    -H "Content-Type: application/json" \
    -d '{"LoginDisclaimer":"<a href=\"https://jellyfin.votre-domaine.tld/sso/OID/p/authentik\">Se connecter avec Authentik</a>","CustomCss":""}'

Deux pièges à connaître

  • System/Configuration/branding attend l'objet BrandingOptions complet. Envoyer seulement LoginDisclaimer sans le reste (CustomCss, etc.) renvoie une erreur 400. Il faut d'abord GET /System/Configuration/branding, fusionner le champ à modifier dans l'objet reçu, puis POST l'ensemble.
  • LoginDisclaimer n'est pas injecté en HTML brut : le client web le passe dans un moteur Markdown (html:true) puis le sanitize avec DOMPurify avant de l'insérer dans le DOM. Les balises <a> sont automatiquement ré-habillées en composant emby-linkbutton (classe button-link ajoutée, target="_blank" forcé). Du HTML/CSS trop custom peut être filtré par le sanitizer.

5. Passer un compte SSO administrateur

Un compte créé via SSO n'est jamais administrateur par défaut. Le plus sûr est de passer par l'API (Users/{id}/Policy) plutôt que d'éditer directement la base SQLite pendant que le service tourne (risque de corruption) :

# Récupérer l'id de l'utilisateur cible
USER_ID=$(curl -s "${JELLYFIN_BASE}/Users" -H "Authorization: MediaBrowser Token=${TOKEN}" \
    | python3 -c "import json,sys; print([u['Id'] for u in json.load(sys.stdin) if u['Name']=='<username>'][0])")

# Récupérer sa policy, activer IsAdministrator, la renvoyer
curl -s "${JELLYFIN_BASE}/Users/${USER_ID}" -H "Authorization: MediaBrowser Token=${TOKEN}" \
    | python3 -c "import json,sys; p=json.load(sys.stdin)['Policy']; p['IsAdministrator']=True; print(json.dumps(p))" \
    | xargs -0 -I{} curl -s -X POST "${JELLYFIN_BASE}/Users/${USER_ID}/Policy" \
        -H "Authorization: MediaBrowser Token=${TOKEN}" -H "Content-Type: application/json" -d {}

Teleport — connecteur OIDC natif

Teleport supporte nativement un connecteur OIDC (kind: oidc) — pas de plugin à installer, uniquement une configuration côté Authentik et un objet Teleport créé via tctl.

1. Créer le provider et l'application dans Authentik

Provider OAuth2/OpenID (Applications → Providers → Create) :

Champ Valeur
Nom Teleport
Client type Confidential
Redirect URIs (strict) https://teleport.votre-domaine.tld/v1/webapi/oidc/callback
Scopes openid, email, profile
Signing key laisser vide (non requis pour ce connecteur)

Puis l'Application correspondante avec un slug (teleport dans cet exemple) — l'endpoint OIDC exposé sera https://auth.votre-domaine.tld/application/o/teleport/. Noter le Client ID et le Client Secret générés par Authentik pour le provider : nécessaires à l'étape suivante.

2. Créer un groupe Authentik pour les administrateurs Teleport

Créer un groupe (ex : teleport-admins) dans Authentik et y ajouter les utilisateurs qui doivent avoir un accès administrateur au cluster. Le nom du groupe doit correspondre à la valeur value du mapping claims_to_roles ci-dessous.

3. Créer le connecteur OIDC dans Teleport

pct exec 204 -- bash -c "cat > /tmp/teleport-oidc.yaml" << 'EOF'
kind: oidc
version: v3
metadata:
  name: authentik
spec:
  issuer_url: https://auth.votre-domaine.tld/application/o/teleport/
  client_id: <client-id-authentik>
  client_secret: <client-secret-authentik>
  redirect_url: https://teleport.votre-domaine.tld/v1/webapi/oidc/callback
  scope:
    - openid
    - profile
    - email
  claims_to_roles:
    - claim: groups
      value: teleport-admins
      roles: [editor, access, auditor]
EOF

pct exec 204 -- /usr/local/bin/tctl create -f /tmp/teleport-oidc.yaml
pct exec 204 -- rm -f /tmp/teleport-oidc.yaml

(remplacer 204 par l'ID réel du conteneur Teleport)

claims_to_roles mappe un groupe Authentik (claim groups du token, valeur teleport-admins) vers un ensemble de rôles Teleport — adapter selon les rôles disponibles dans votre cluster (tctl get roles pour la liste).

Vérifier le connecteur : pct exec 204 -- tctl get oidc/authentik. La connexion SSO est ensuite disponible depuis l'écran de login web (https://teleport.votre-domaine.tld), en plus de l'authentification locale existante — à garder active comme accès de secours si Authentik devient indisponible.


FileBrowser Quantum — configuration native

Quantum a un support OIDC natif — pas de plugin à installer, uniquement de la configuration.

1. Créer le provider et l'application dans Authentik

Provider OAuth2/OpenID (Applications → Providers → Create) :

Champ Valeur
Nom Filebrowser
Client type Confidential
Client ID filebrowser
Client Secret généré (openssl rand -hex 32)
Redirect URIs (strict) https://files.votre-domaine.tld/api/auth/oidc/callback
Scopes openid, email, profile

Puis l'Application correspondante avec un slug (filebrowser dans cet exemple) — l'endpoint OIDC exposé sera https://auth.votre-domaine.tld/application/o/filebrowser/.

2. Compléter config.yaml

auth:
  methods:
    password:
      enabled: false
    oidc:
      enabled: true
      clientId: "filebrowser"
      clientSecret: "<client-secret-authentik>"
      issuerUrl: "https://auth.votre-domaine.tld/application/o/filebrowser/"
      scopes: "openid email profile"
      userIdentifier: "preferred_username"
pct exec 202 -- systemctl restart filebrowser

(remplacer 202 par l'ID réel du conteneur FileBrowser)

Une source ajoutée après coup n'est pas rétroactive pour les comptes existants

Si une nouvelle entrée est ajoutée dans server.sources (ex : un point de montage partagé avec un autre service) avec config.defaultEnabled: true, seuls les nouveaux comptes créés après l'ajout y ont automatiquement accès. Les comptes déjà créés (y compris via OIDC) doivent recevoir l'accès manuellement : Settings → Users → éditer l'utilisateur → ajouter la source.