OAuth2 Nextcloud permet à une application cliente d’accéder au compte d’un utilisateur après une autorisation dans le navigateur. Le serveur remet alors un jeton temporaire à l’application, sans lui transmettre le mot de passe Nextcloud.
Ce mécanisme convient à une application web avec un backend capable de protéger un secret client. Il ne convient pas à une application qui ne peut pas garder ce secret, ni à un projet qui cherche seulement un bouton de connexion pour authentifier ses propres utilisateurs. La mise en œuvre Nextcloud accepte uniquement les clients confidentiels et ne propose pas de droits OAuth2 limités par des scopes. Le jeton peut donc lire et modifier tout ce que le compte autorisé peut atteindre.
OAuth2 Nextcloud répond-il vraiment au besoin ?
Dans ce flux, Nextcloud joue le rôle de serveur d’autorisation. Une application externe demande l’accès à un compte Nextcloud, l’utilisateur se connecte et confirme, puis l’application reçoit un code à échanger contre des jetons. Elle utilise ensuite le jeton d’accès pour appeler WebDAV ou une API Nextcloud avec l’identité de cet utilisateur.
Cette direction est différente d’une connexion SSO à Nextcloud. Si l’objectif consiste à faire authentifier les utilisateurs de Nextcloud par un fournisseur d’identité externe, il faut étudier OIDC, SAML ou LDAP. Le guide Nextcloud avec SSO et LDAP détaille cette architecture entrante.
Voici la décision selon le type d’intégration :
- Backend métier après consentement : le flux est adapté, avec les limites de droits décrites ci-dessous.
- Application monopage : ne l’utilisez pas, car le secret ne peut pas être protégé dans le navigateur.
- Application mobile native : ne stockez pas le secret dans le binaire. Nextcloud ne prend en charge que les clients confidentiels dans ce flux.
- Bouton de connexion pour identifier les utilisateurs de votre propre service : utilisez un fournisseur d’identité adapté. Nextcloud déconseille cet usage sans scopes restrictifs.
- Traitement automatique avec un compte propre : un compte dédié et un périmètre de fichiers partagé peuvent convenir, à condition de tester la rotation et la révocation.
Un jeton OAuth2 Nextcloud n’est pas limité à un dossier
La documentation officielle précise que les scopes ne sont pas pris en charge. Chaque jeton possède l’accès complet du compte, y compris la lecture et l’écriture des fichiers autorisés pour ce compte. La réduction du périmètre passe donc par le choix du compte, ses groupes et ses partages, pas par un paramètre OAuth2.
Pour replacer ce flux parmi WebDAV, OCS et les autres interfaces, consultez le guide de l’API Nextcloud. Le présent article reste centré sur l’autorisation, la rotation des jetons et la révocation.
Comment enregistrer le client OAuth2 dans Nextcloud ?
Connectez-vous avec un compte administrateur, ouvrez les paramètres d’administration puis la section Sécurité. Dans le bloc OAuth2, ajoutez un client avec deux informations :
- un nom qui identifie clairement l’application et son environnement, par exemple
ERP facturation production; - l’URL HTTPS complète et stable du callback de votre backend.
Nextcloud génère ensuite un identifiant client et un secret client. Copiez le secret dès cette étape et placez-le dans un gestionnaire de secrets. Le serveur conserve une empreinte du secret et l’interface ne recharge pas sa valeur en clair dans la liste des clients existants.
L’URL de retour doit pointer vers le backend qui traite le code d’autorisation. Dans le fonctionnement normal, Nextcloud reprend l’URL enregistrée pour renvoyer l’utilisateur. Ne construisez donc pas une seule fiche client pour plusieurs domaines, environnements ou chemins de callback. Créez un client distinct pour le développement, la préproduction et la production.
Préparez les valeurs suivantes côté serveur :
NC_URL="https://cloud.exemple.fr"
CLIENT_ID="IDENTIFIANT_CLIENT"
CLIENT_SECRET="SECRET_CLIENT"
CALLBACK_URL="https://erp.exemple.fr/oauth/nextcloud/callback"
CLIENT_SECRET ne doit jamais apparaître dans le JavaScript livré au navigateur, une application mobile, une URL, un dépôt Git ou des journaux. Le guide des mots de passe d’application Nextcloud présente une autre méthode pour les clients directs qui n’emploient pas ce flux OAuth2.
Comment lancer le flux d’autorisation par code ?
Le client génère d’abord une valeur state aléatoire, l’associe à la session locale de l’utilisateur puis redirige le navigateur vers l’endpoint d’autorisation :
https://cloud.exemple.fr/apps/oauth2/authorize
?client_id=IDENTIFIANT_CLIENT
&response_type=code
&state=VALEUR_ALEATOIRE_LIEE_A_LA_SESSION
La valeur réelle doit être encodée dans l’URL. Elle ne sert pas de secret d’accès, mais elle permet de relier le callback à la demande partie du même navigateur. À la réception, comparez la valeur retournée à celle conservée en session avec une comparaison sûre. Refusez le callback si elle manque, diffère ou a déjà été consommée.
Nextcloud accepte uniquement response_type=code dans ce flux. L’utilisateur choisit son compte, s’authentifie puis confirme l’accès. Le serveur le renvoie vers l’URL enregistrée avec deux paramètres :
https://erp.exemple.fr/oauth/nextcloud/callback
?state=VALEUR_RETOURNEE
&code=CODE_AUTORISATION
Le code est temporaire et à usage unique. Dans Nextcloud 34, le contrôleur OAuth2 fixe sa durée de validité à dix minutes. Votre backend doit donc vérifier state, échanger le code immédiatement, puis supprimer le code et l’état de la session locale.
L’URL de callback doit rester stable
Une redirection variable complique la validation et augmente le risque d’envoyer le code au mauvais destinataire. Enregistrez une URL HTTPS précise par environnement, puis effectuez la navigation finale dans votre application après avoir traité le callback côté serveur.
Comment échanger le code contre les jetons ?
L’endpoint de jeton est :
https://cloud.exemple.fr/apps/oauth2/api/v1/token
Si les URL simplifiées ne sont pas configurées sur l’instance, la documentation demande de conserver index.php dans le chemin. Le backend peut transmettre l’identifiant et le secret avec une authentification HTTP Basic. Cette méthode évite de placer le secret dans l’URL :
curl --fail-with-body \
--user "$CLIENT_ID:$CLIENT_SECRET" \
--request POST \
--data-urlencode "grant_type=authorization_code" \
--data-urlencode "code=$AUTHORIZATION_CODE" \
"$NC_URL/apps/oauth2/api/v1/token"
Une réponse réussie possède cette structure. Les valeurs opaques ci-dessous sont des emplacements, pas des jetons utilisables :
{
"access_token": "<jeton-acces-opaque>",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "<jeton-renouvellement-opaque>",
"user_id": "identifiant-nextcloud"
}
Le jeton d’accès expire après 3 600 secondes, soit une heure. user_id fournit l’identifiant Nextcloud à employer dans les chemins qui le demandent. Conservez le jeton d’accès, le jeton de renouvellement, leur échéance et l’identité du compte dans un stockage chiffré réservé au backend.
Ne journalisez ni la réponse complète ni l’en-tête Authorization. Pour diagnostiquer le flux, enregistrez plutôt l’identifiant interne de l’intégration, l’heure, l’étape, le code HTTP et une catégorie d’erreur sans secret.
Comment appeler WebDAV ou une API avec le jeton Bearer ?
Le jeton d’accès se transmet dans l’en-tête Authorization: Bearer. Cet exemple effectue un PROPFIND limité à la racine WebDAV du compte retourné par l’endpoint de jeton :
curl --fail-with-body \
--request PROPFIND \
--header "Authorization: Bearer $ACCESS_TOKEN" \
--header "Depth: 0" \
"$NC_URL/remote.php/dav/files/$NC_USER_ID/"
Une réponse 207 Multi-Status indique habituellement que WebDAV a traité la demande. Le corps XML doit encore être analysé pour vérifier le statut de la ressource demandée. Pour une API OCS, ajoutez les en-têtes requis par l’endpoint concerné, notamment OCS-APIRequest: true lorsqu’il est documenté.
L’autorisation ne crée aucun périmètre supplémentaire. Si le compte peut supprimer un dossier, modifier un partage ou consulter plusieurs espaces, le jeton peut exercer ces mêmes droits par les interfaces qui les exposent. Pour une intégration machine, un compte dédié auquel seuls les dossiers nécessaires sont partagés réduit les conséquences d’un jeton compromis. Le guide complet de Nextcloud aide à replacer comptes, partages et applications dans l’architecture générale.
Comment renouveler le jeton sans perdre la connexion ?
Avant l’expiration du jeton d’accès, envoyez le dernier jeton de renouvellement à l’endpoint de jeton :
curl --fail-with-body \
--user "$CLIENT_ID:$CLIENT_SECRET" \
--request POST \
--data-urlencode "grant_type=refresh_token" \
--data-urlencode "refresh_token=$REFRESH_TOKEN" \
"$NC_URL/apps/oauth2/api/v1/token"
Nextcloud renvoie un nouveau jeton d’accès d’une heure et un nouveau jeton de renouvellement. Le code serveur fait tourner les deux valeurs et refuse la réutilisation de l’ancien jeton de renouvellement. Cette propriété empêche deux workers d’effectuer le même renouvellement en parallèle sans coordination.
La conséquence opérationnelle est importante : verrouillez le renouvellement par connexion, puis enregistrez atomiquement la nouvelle paire avant de libérer le verrou. Si deux processus utilisent le même ancien jeton, un seul obtient la rotation. Si votre application reçoit la nouvelle paire mais ne la sauvegarde pas, elle ne pourra pas reprendre avec l’ancienne valeur et devra recommencer une autorisation utilisateur.
Une stratégie simple consiste à :
- renouveler quelques minutes avant l’expiration, pas à chaque requête ;
- poser un verrou unique pour le compte et le client concernés ;
- envoyer le dernier
refresh_tokenstocké ; - écrire ensemble le nouvel
access_token, le nouveaurefresh_tokenet l’échéance ; - libérer le verrou puis reprendre les appels API ;
- demander une nouvelle autorisation après un
invalid_requestpersistant, sans répéter en boucle.
Comment révoquer un client ou réagir à une fuite ?
Pour une révocation globale, supprimez le client dans les paramètres d’administration, section Sécurité. Dans Nextcloud 34, cette suppression invalide les jetons d’application associés au nom du client et retire les entrées OAuth2 liées à ce client. Toutes les connexions de cette application doivent ensuite être autorisées de nouveau.
Le flux documenté expose l’ajout et la suppression d’un client, pas une rotation autonome du secret. Si le secret client est compromis, créez un nouveau client avec une nouvelle paire d’identifiants, mettez à jour le backend, testez-le, puis supprimez l’ancien client. Garder l’ancienne fiche après une fuite laisse son secret utilisable tant qu’elle n’est pas révoquée.
Traitez séparément trois incidents :
- jeton d’accès exposé : coupez rapidement l’accès concerné, car le jeton est un Bearer utilisable sans preuve supplémentaire pendant sa validité ;
- jeton de renouvellement exposé : révoquez la connexion ou le client, car il permet d’obtenir une nouvelle paire ;
- secret client exposé : remplacez le client, puis réautorisez les comptes nécessaires.
Ne considérez pas l’expiration d’une heure comme une réponse suffisante. Le jeton de renouvellement maintient la connexion, et l’absence de scopes augmente l’impact possible sur le compte.
Quelles erreurs faut-il diagnostiquer ?
- Le client n’est pas autorisé à se connecter : le
client_idest inconnu ou le client a été supprimé. Comparez l’identifiant avec la fiche de l’environnement actif. - Retour
unsupported_response_type: envoyez exactementresponse_type=code. - Retour
invalid_requestlors de l’échange : le code peut être expiré, déjà consommé ou le jeton de renouvellement obsolète. Reprenez le flux ou chargez la dernière paire stockée. - Retour
invalid_client: vérifiez l’identifiant, le secret et l’environnement dans le coffre de secrets. - Appel API en
401après un renouvellement : invalidez le cache local et chargez la nouvelle paire de jetons. - Échecs intermittents pendant les renouvellements : deux workers utilisent probablement le même jeton. Ajoutez un verrou et une écriture atomique.
- Accès à plus de données que prévu : aucun scope restrictif n’est disponible. Réduisez les droits du compte et ses partages.
Vérifiez aussi le chemin de l’endpoint. Une instance sans URL simplifiée peut nécessiter /index.php/apps/oauth2/.... Si le jeton est accepté par Nextcloud mais absent du serveur web, la documentation signale qu’Apache peut retirer l’en-tête Authorization lorsque les modules et règles nécessaires ne sont pas en place.
Quelle recette valider avant la production ?
Une recette minimale doit couvrir le flux heureux et les ruptures de sécurité :
- créer un client réservé à l’environnement de test ;
- autoriser un compte pilote sans privilèges d’administration ;
- refuser un callback dont
statediffère ; - échanger le code une seule fois, puis vérifier que sa réutilisation échoue ;
- appeler une ressource autorisée et une ressource interdite ;
- renouveler le jeton et confirmer que l’ancien jeton de renouvellement est refusé ;
- simuler deux renouvellements concurrents ;
- supprimer le client et vérifier que les appels suivants échouent ;
- contrôler que les journaux, traces et alertes ne contiennent aucun jeton ;
- documenter la personne capable de révoquer et de réautoriser le client.
Le verdict est simple : le fournisseur OAuth2 intégré convient à un backend confidentiel qui doit agir sur un compte Nextcloud après consentement. Il exige toutefois une gestion stricte du secret, de state, de la rotation et de la révocation. L’absence de scopes exclut les usages où l’application devrait recevoir seulement un profil ou un dossier isolé sans réduire les droits du compte lui-même.
Sources officielles
- OAuth2 dans le manuel d’administration Nextcloud 34
- Routes OAuth2 du serveur Nextcloud 34
- Autorisation et validation du client dans Nextcloud 34
- Échange, expiration et rotation des jetons dans Nextcloud 34
- Création et suppression des clients OAuth2 dans Nextcloud 34
- RFC 6749, OAuth 2.0 Authorization Framework