🔐 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 slug — jellyfin 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/brandingattend l'objetBrandingOptionscomplet. Envoyer seulementLoginDisclaimersans le reste (CustomCss, etc.) renvoie une erreur 400. Il faut d'abordGET /System/Configuration/branding, fusionner le champ à modifier dans l'objet reçu, puisPOSTl'ensemble.LoginDisclaimern'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 composantemby-linkbutton(classebutton-linkajouté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.