WakaStart
Sécurité

Contrôle d'accès — Modèle & Cascade

Les 2 vecteurs de droits Wakastart : adminLevel et appRights (droits resource.action), et la vérification de features activées.

Version v1.04 min de lecture

Contrôle d'accès — Modèle & Cascade

Le contrôle d'accès est double : le backend bloque toujours (source d'autorité), le frontend masque (UX). Ne faites jamais confiance au frontend seul pour sécuriser une action.

Concepts clés

  • adminLevel : niveau hiérarchique, détermine la portée des opérations CRUD.
  • appRights : droits fins sur des ressources spécifiques (users.create, infra.deploy…), dérivés des profils. Le claim JWT correspondant s'appelle roles (format resource.action) ; côté /me, ils apparaissent sous profile.rights (tableau d'objets {code, name, description, category}, pas un simple tableau de strings).
  • features : activation en cascade App ∧ Network ∧ Customer. Si une feature est désactivée à n'importe quel niveau, elle est indisponible.
  • Profile : ensemble de AppRight assigné à un utilisateur. Un utilisateur peut avoir plusieurs profils.

Un ancien 3ᵉ vecteur, wakaRoles (rôles métier transversaux type CONFIG/EXPLOIT/DPO/AUDIT/BILLING/CYBER), a été décommissionné côté plateforme. Les vérifications de droits reposent désormais uniquement sur adminLevel et les codes resource.action issus des profils — ignorez toute mention de wakaRoles dans du code ou de la documentation plus ancienne.


Les 2 vecteurs de droits

1. adminLevel — portée hiérarchique

Contrôle qui peut voir et modifier quoi selon la position dans la hiérarchie multi-tenant.

text
WakaAdmin → Tout (plateforme complète, tous les Partners) OwnerAdmin → Tout (propriétaire du Partner) AppsAdmin → Applications + Profils + Droits (dans son Network) NetworkAdmin → Réseaux + Customers + Apps (dans son Network) CustomerAdmin → Customers + Users + Teams (dans son Customer) User → Son propre profil uniquement None → Aucun accès admin

Règle de hiérarchie : un NetworkAdmin possède implicitement les droits de CustomerAdmin et User. La vérification côté backend utilise une comparaison ordinale.

2. appRights — droits applicatifs fins

Droits de type {resource}.{action} accumulés depuis les profils de l'utilisateur.

Format : resource.action ou resource.sub-resource.action

Exemples :

text
partners.read users.create infra.deploy partners.write users.update infra.services.scale apps.read users.delete audit.read apps.create teams.read billing.manage apps.delete teams.members.add api-keys.read profiles.read teams.members.remove api-keys.create profiles.assign invitations.create api-keys.revoke profiles.rights.write invitations.read media.upload

Cascade de features

Une feature doit être activée à trois niveaux pour être disponible :

Chargement du diagramme…

Le payload /me n'expose pas de champ features précalculé. Vérifiez l'activation d'une feature via l'endpoint dédié : GET /api/config/app-features/check/{customerWid}/{featureCode}.

Exemple concret :

typescript
// Si la feature "invitations" est désactivée à un niveau quelconque → masquer tout le module const { data } = await api.get(`/api/config/app-features/check/${customerWid}/invitations`); const hasInvitations = data.enabled;

Vérification combinée via /token/authorize

Pour des vérifications complexes (admin level + rôle + droit) en un seul appel :

http
POST /api/token/authorize x-api-key: sk_live_... Content-Type: application/json { "token": "eyJ...", "checks": { "adminLevel": { "requiredLevel": "CustomerAdmin" }, "roles": { "roles": ["audit.read", "billing.manage"], "mode": "any" }, "appRights": { "rights": ["users.create", "users.update"], "mode": "all" } } }
json
{ "authorized": true, "details": { "adminLevel": { "hasLevel": true, "actualLevel": "NetworkAdmin" }, "roles": { "hasRoles": true, "matchedRoles": ["audit.read"] }, "appRights": { "hasRights": true, "missingRights": [] } } }

Bonnes pratiques

  • Principe du moindre privilège : n'accordez que les droits strictement nécessaires dans les profils.
  • Backend = autorité : vérifiez toujours les droits côté serveur. Le frontend ne fait que masquer.
  • Granularité fine : préférez users.create à users.* — les wildcards n'existent pas dans le modèle.
  • Features en premier : avant de vérifier un droit, vérifiez si la feature est activée.

Pièges classiques

  • Confondre trois concepts voisins : adminLevel (ADMIN, TEAM, INVITE, USER, EXTERN, NONE) est la portée administrative sur la hiérarchie ; teamLevel (ADMIN, MANAGER, MEMBER, CONTRIBUTOR, VIEWER, NONE) est le rôle au sein d'une équipe précise — MEMBER appartient à teamLevel, pas à adminLevel.
  • appRights vide = aucun accès : un utilisateur sans profil assigné a appRights: [] et ne voit rien.
  • Feature désactivée → 403 : si GET /api/config/app-features/check/{customerWid}/{featureCode} renvoie enabled: false et que votre code appelle quand même l'API, vous obtiendrez un 403 Feature désactivée.
  • Droits cumulatifs : si l'utilisateur a deux profils, ses appRights sont l'union des deux.

Aller plus loin