Aller au contenu
Bondry

OAuth 2.1 pour les applications

Le code d'autorisation avec PKCE, la rotation des refresh tokens, les scopes et les endpoints qu'une application appelle.

Les clés d'API couvrent les intégrations de serveur à serveur. OAuth est là pour une application qui agit au nom d'un membre, avec le consentement de ce membre : une application mobile, ou un outil tiers qu'un membre connecte à son compte.

Les flux#

  • Le code d'autorisation avec PKCE (S256), obligatoire pour tout client. Les clients publics comme les applications mobiles ne portent aucun secret ; les clients confidentiels peuvent en avoir un.
  • Les refresh tokens tournent. Chaque utilisation en émet un nouveau et invalide le précédent. Réutiliser un token déjà tourné révoque toute la famille, et c'est ainsi qu'un token volé est détecté.
  • Pas de flux implicite, pas de password grant. L'autorisation par appareil n'est pas dans la v1.

Les endpoints#

Endpoint Ce qu'il fait
GET /oauth/authorize L'écran de consentement, dans la session du membre, qui liste les scopes en langage clair
POST /oauth/token Les grants authorization_code et refresh_token
POST /oauth/revoke Révoque un token
GET /oauth/userinfo Le profil minimal, selon les scopes accordés
GET /.well-known/oauth-authorization-server Les métadonnées, RFC 8414

La durée de vie des tokens#

Artefact Durée de vie Notes
Code d'autorisation 60 secondes Usage unique
Access token 1 heure Opaque, pas un JWT ; stocké sous forme de hash SHA-256
Refresh token 30 jours Rotatif

Les access tokens sont opaques volontairement. Un JWT qu'on ne peut pas révoquer avant son expiration est le mauvais compromis pour une application qu'un membre peut déconnecter à tout moment.

Les URIs de redirection#

Enregistrées par client et comparées à l'identique. Les schémas personnalisés (bondry-app://callback) et le loopback (http://127.0.0.1:<port>) sont autorisés pour les applications natives ; localhost n'est accepté qu'en environnement local.

Les scopes#

Les mêmes scopes que pour les clés d'API, déclarés par le core et par chaque module : members.read, community.write, blog.read, messages.*, notifications.*, account.*, plus profile pour l'identité minimale et offline_access pour un refresh token.

Le contrôle d'accès accepte un bearer token venant d'OAuth ou d'une clé d'API. Un token OAuth porte le membre, donc les permissions de groupe du membre s'appliquent par-dessus le scope.

Avertissement Un scope n'élargit jamais ce que le membre ne peut pas faire. Demander community.write pour un membre qui ne peut pas publier échoue quand même.

Enregistrer un client#

System > API > OAuth clients dans le panneau : nom, logo, site web, URIs de redirection, et si le client est confidentiel. Le secret d'un client confidentiel n'est affiché qu'une seule fois. Chaque modification est écrite dans le journal d'administration.

Ce que le membre voit#

  • L'écran de consentement, rendu dans le thème du site, avec le nom et le logo de l'application, les scopes expliqués, un avertissement explicite quand l'application n'est pas first party, et les deux boutons Autoriser et Refuser.
  • Account > Connected apps, qui liste chaque application autorisée avec ses scopes et sa dernière utilisation, et un bouton qui révoque l'application et toute sa famille de tokens.

La révocation se propage en cascade : bannir ou supprimer un membre, ou révoquer le client, révoque les tokens.

Notes d'implémentation#

  • state est obligatoire et renvoyé tel quel.
  • PKCE est obligatoire, avec S256.
  • Les comparaisons de hash sont à temps constant.
  • /oauth/token est soumis à une limite de débit par client et par IP.
  • Les tokens n'apparaissent jamais dans un log.

Chaque flux et chaque refus a un test : vérificateur PKCE erroné, URI de redirection différente, code réutilisé, refresh token déjà tourné et réutilisé, scope non accordé, membre banni.