> Discover all available pages from the documentation index: https://mastra.zisheng.pro/fr/llms.txt # Autorisation granulaire (FGA) > **Remarque:** L'autorisation granulaire fait partie de l'édition Entreprise de Mastra. Les déploiements en production nécessitent une licence EE valide. [Contactez l'équipe commerciale](https://mastra.ai/contact) pour en savoir plus. L'autorisation granulaire (FGA) ajoute à votre application Mastra des contrôles d'autorisation au niveau des ressources. Alors que le RBAC répond à la question « ce rôle peut-il effectuer cette action ? », la FGA répond à **« cet utilisateur peut-il effectuer cette action sur cette ressource précise ? »** ## Quand utiliser la FGA La FGA est conçue pour les produits B2B mutualisés, dans lesquels les autorisations dépendent du contexte : - Un utilisateur peut être **administrateur** de l'équipe A, mais seulement **membre** de l'équipe B. - L'accès aux threads doit être limité à l'organisation de l'utilisateur. - L'exécution d'un workflow doit être restreinte à une équipe ou à un projet précis. - L'accès aux outils dépend de la relation entre l'utilisateur et une ressource. ## Configuration Configurez la FGA dans la configuration de votre serveur Mastra, aux côtés de l'authentification et du RBAC : ```typescript import { Mastra } from '@mastra/core/mastra'; import { MastraFGAPermissions } from '@mastra/core/auth/ee'; import { MastraAuthWorkos, MastraFGAWorkos } from '@mastra/auth-workos'; const mastra = new Mastra({ server: { auth: new MastraAuthWorkos({ /* ... */ fetchMemberships: true, mapUserToResourceId: user => user.teamId, }), fga: new MastraFGAWorkos({ resourceMapping: { agent: { fgaResourceType: 'team', deriveId: (ctx) => ctx.user.teamId }, workflow: { fgaResourceType: 'team', deriveId: (ctx) => ctx.user.teamId }, thread: { fgaResourceType: 'workspace-thread', deriveId: ({ resourceId }) => resourceId }, }, permissionMapping: { [MastraFGAPermissions.AGENTS_EXECUTE]: 'manage-workflows', [MastraFGAPermissions.WORKFLOWS_EXECUTE]: 'manage-workflows', [MastraFGAPermissions.MEMORY_READ]: 'read', [MastraFGAPermissions.MEMORY_WRITE]: 'update', }, }), storedResources: { scope: true, }, }, }); ``` Lorsque vous utilisez `MastraFGAWorkos`, définissez `fetchMemberships: true` sur `MastraAuthWorkos`. Les contrôles FGA de WorkOS ont besoin des appartenances de l'utilisateur aux organisations afin de déterminer l'ID d'appartenance approprié pour l'autorisation. Utilisez `thread` comme clé de mappage de ressource pour l'autorisation de la mémoire. `MastraFGAWorkos` accepte toujours l'ancien alias `memory`, mais les nouvelles configurations doivent privilégier `thread`. Lorsque `server.fga` est configuré, Mastra applique la FGA aux actions protégées. Si aucune personne authentifiée n'est associée à une action protégée, Mastra refuse cette action. Si `server.fga` n'est pas configuré, ces contrôles FGA sont ignorés et Mastra conserve le comportement antérieur. ### Mappage des ressources `resourceMapping` indique à Mastra comment déterminer les types et les ID des ressources FGA à partir du contexte de requête. Les clés correspondent aux types de ressources Mastra ; les valeurs définissent le type de ressource FGA et la manière de calculer son ID : ```typescript resourceMapping: { // When checking "can user execute agent X?", resolve the FGA resource // as the user's team (type: 'team', id: user.teamId) agent: { fgaResourceType: 'team', deriveId: (ctx) => ctx.user.teamId, }, } ``` `deriveId()` reçoit : - `user` : l'utilisateur authentifié - `resourceId` : l'ID de la ressource Mastra propriétaire lorsqu'il est disponible (par exemple, le `resourceId` d'un thread) - `requestContext` : le contexte de requête actuel, pour une résolution avancée du tenant - `metadata` : les métadonnées propres au fournisseur pour l'action tentée Renvoyez `undefined` depuis `deriveId()` pour utiliser à défaut l'ID d'origine de la ressource Mastra. Pour les contrôles portant sur les threads et la mémoire, Mastra transmet toujours le `threadId` brut comme ressource à vérifier, mais fournit également le `resourceId` propriétaire du thread à `deriveId()`. Vous pouvez ainsi associer les autorisations d'un thread à des ID de tenant composites, comme `userId-teamId-orgId`. ### Mappage des autorisations `permissionMapping` traduit les chaînes d'autorisation internes de Mastra en slugs d'autorisation utilisés par votre fournisseur FGA : ```typescript import { MastraFGAPermissions } from '@mastra/core/auth/ee'; permissionMapping: { [MastraFGAPermissions.AGENTS_EXECUTE]: 'manage-workflows', // Mastra permission -> WorkOS permission slug [MastraFGAPermissions.MEMORY_READ]: 'read', } ``` Si aucun mappage n'existe pour une autorisation, la chaîne d'origine est transmise telle quelle. Utilisez `validatePermissions()` pour valider au démarrage l'ensemble des autorisations que Mastra est susceptible d'émettre. Cette validation est utile lorsqu'un fournisseur exige que chaque autorisation Mastra possède un slug explicite propre au fournisseur. ### Délimitation des ressources stockées La FGA autorise l'accès à une ressource, mais ne filtre pas automatiquement les enregistrements conservés dans un stockage partagé. Activez la délimitation des ressources stockées lorsque les API intégrées correspondantes sont utilisées dans une application mutualisée. ```typescript const mastra = new Mastra({ server: { auth: new MastraAuthWorkos({ /* ... */ mapUserToResourceId: user => user.teamId, }), storedResources: { scope: true, }, }, }); ``` Avec `scope: true`, Mastra lit `MASTRA_RESOURCE_ID_KEY` dans le contexte de requête. `mapUserToResourceId()` définit cette valeur après l'authentification. Les gestionnaires de ressources stockées conservent la portée dans les métadonnées de l'enregistrement et filtrent selon cette portée les opérations de listage, de lecture, de mise à jour, de publication et de suppression. Utilisez un objet lorsque la portée nécessite une logique de requête personnalisée : ```typescript storedResources: { scope: { metadataKey: 'teamId', resolve: ({ user }) => user.teamId, requireScope: true, }, }, ``` Si `requireScope` vaut `true` ou n'est pas défini, les routes de ressources stockées délimitées échouent lorsqu'aucune portée ne peut être déterminée. ### Couverture des politiques de route Mastra inclut des métadonnées FGA au niveau des routes pour les routes de ressources intégrées, notamment celles des agents, workflows, outils, outils MCP, threads de mémoire, réponses, conversations et ressources stockées. La couverture des routes de ressources stockées comprend `/stored/agents`, `/stored/mcp-clients`, `/stored/prompt-blocks`, `/stored/scorers`, `/stored/skills` et `/stored/workspaces`. Une route est contrôlée si elle possède des métadonnées `fga` au niveau de la route, si Mastra peut en déduire les métadonnées intégrées, ou si le fournisseur fournit des métadonnées avec `resolveRouteFGA()`. Pour refuser les routes protégées dont les métadonnées FGA ne peuvent pas être déterminées, configurez la couverture des politiques de route sur le fournisseur FGA : ```typescript const fga = new MastraFGAWorkos({ resourceMapping: { project: { fgaResourceType: 'project' }, }, permissionMapping: { 'projects:read': 'read', }, requireForProtectedRoutes: true, auditProtectedRoutes: 'warn', validatePermissions: async permissions => { // Throw if a Mastra permission is missing from permissionMapping. }, }); ``` Définissez `auditProtectedRoutes: 'error'` afin de faire échouer le démarrage lorsque des routes protégées ne disposent pas de métadonnées FGA intégrées. Si `requireForProtectedRoutes` est activé, Mastra consigne par défaut cet audit sous forme d'avertissement. Pour les routes personnalisées, privilégiez les métadonnées `fga` au niveau de la route. La politique d'autorisation reste ainsi définie à proximité de celle-ci : ```typescript import { createRoute } from '@mastra/server/server-adapter'; export const getProjectRoute = createRoute({ method: 'GET', path: '/projects/:projectId', responseType: 'json', requiresAuth: true, fga: { resourceType: 'project', resourceIdParam: 'projectId', permission: 'projects:read', }, handler: async () => { return { project: null }; }, }); ``` N'utilisez `resolveRouteFGA()` que lorsque les métadonnées doivent être calculées de manière centralisée à partir de la route, de ses paramètres ou du contexte de requête. Une table de routes s'adapte mieux à la montée en charge que des contrôles fondés sur le préfixe d'une chaîne : ```typescript import type { FGARouteConfig, FGARouteResolver } from '@mastra/core/auth/ee'; const routeFGA = { 'GET /billing/:accountId': { resourceType: 'account', resourceIdParam: 'accountId', permission: 'billing:read', }, } satisfies Record; const resolveRouteFGA: FGARouteResolver = ({ route }) => routeFGA[`${route.method} ${route.path}`]; const fga = new MastraFGAWorkos({ /* ... */ resolveRouteFGA, }); ``` ## Points d'application Lorsqu'un fournisseur FGA est configuré, Mastra contrôle automatiquement les autorisations aux points suivants du cycle de vie : | Point du cycle de vie | Autorisation contrôlée | Type de ressource | ID de la ressource | | ----------------------------------------------------------------------- | ------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | | Exécution d'un agent (`generate`, `stream`) | `agents:execute` | `agent` | `agentId` | | Routes HTTP intégrées d'exécution des workflows et `Workflow.execute()` | `workflows:execute` | `workflow` | `workflowId` | | Exécution d'un outil autonome | `tools:execute` | `tool` | `toolName` | | Exécution d'un outil par un agent | `tools:execute` | `tool` | `${agentId}:${toolName}` | | Exécution d'un outil MCP | `tools:execute` | `tool` par défaut, ou la redéfinition `fga.resourceMapping` au niveau du serveur | `JSON.stringify([serverName, toolName])` par défaut, ou l'ID calculé au niveau du serveur | | Accès aux threads et à la mémoire | `memory:read`, `memory:write`, `memory:delete` | `thread` | `threadId` | | Routes de ressources stockées | Autorisation de la ressource stockée correspondant à l'action de la route | Type de ressource stockée | ID de l'enregistrement de la route, ou portée de la ressource stockée pour les routes de collection | | Routes HTTP de ressources | Configuré pour chaque route | Configuré pour chaque route | Configuré pour chaque route | Pour les serveurs MCP protégés par OAuth, les transports HTTP MCP transmettent les données authentifiées sous la forme `extra.authInfo`. Si un `MCPServer` est enregistré sur une instance Mastra utilisant la FGA, configurez `mapAuthInfoToUser` afin que Mastra puisse définir `requestContext.get('user')` avant de contrôler `tools/list` et `tools/call`. Utilisez l'option `fga` au niveau du serveur lorsque les contrôles des outils MCP nécessitent un mappage de ressources ou d'autorisations différent de celui des outils internes des agents et des workflows. Consultez le [contexte d'authentification de MCPServer](https://mastra.zisheng.pro/fr/reference/tools/mcp-server). Dans cette version, les appels directs du SDK à `createRun().start()`, `resume()` ou `restart()` ne sont pas contrôlés indépendamment par le cœur de la FGA. Effectuez ces appels depuis une route protégée ou sécurisez-les dans le code de l'application. Transmettez un `requestContext` contenant un utilisateur authentifié lorsque vous appelez directement des points d'entrée protégés. Les contrôles effectués par le cœur sur les agents, les workflows internes, les outils et la mémoire transmettent également le `requestContext` et les métadonnées de l'action au fournisseur FGA. Les contrôles de route transmettent le `requestContext`. Ceux des threads transmettent le `resourceId` propriétaire lorsqu'il est disponible. ## Fournisseur FGA personnalisé Implémentez `IFGAProvider` pour utiliser n'importe quel backend FGA : ```typescript import { FGADeniedError } from '@mastra/core/auth/ee' import type { FGACheckParams, IFGAProvider, MastraFGAPermissionInput } from '@mastra/core/auth/ee' class MyFGAProvider implements IFGAProvider { async check(user: any, params: FGACheckParams): Promise { // Your authorization logic return true } async require(user: any, params: FGACheckParams): Promise { const allowed = await this.check(user, params) if (!allowed) { throw new FGADeniedError(user, params.resource, params.permission) } } async filterAccessible( user: any, resources: T[], resourceType: string, permission: MastraFGAPermissionInput, ): Promise { // Filter resources the user can access return resources } } ``` > **Remarque:** Consultez la [référence de `IFGAProvider`](https://mastra.zisheng.pro/fr/reference/auth/fga) pour découvrir l'ensemble des méthodes et paramètres, ainsi que le type `ActorSignal`. ## Acteurs système Les agents autonomes et planifiés s'exécutent sans utilisateur final. Marquez ces appels à l'aide d'un signal d'acteur afin que la FGA puisse les distinguer des requêtes utilisateur : - `true` ou `{ actorKind: 'system' }` identifie un acteur système anonyme. - La forme objet peut également contenir `agentId`, `permissions` et `scope` afin d'identifier et de restreindre l'agent qui agit. Par défaut, après un contrôle de la portée du tenant, un acteur de confiance contourne le contrôle `require()` centré sur l'utilisateur. Pour appliquer le principe du moindre privilège à chaque agent, implémentez la méthode facultative `requireActor` sur votre fournisseur. Elle reçoit l'acteur ainsi que les mêmes `FGACheckParams` que `require`, puis lève `FGADeniedError` en cas de refus. Lorsque votre fournisseur n'implémente pas `requireActor`, le contournement accordé aux acteurs de confiance reste en vigueur ; l'ajout de cette méthode est donc rétrocompatible. ```typescript import { FGADeniedError } from '@mastra/core/auth/ee' import type { ActorSignal, FGACheckParams, IFGAProvider } from '@mastra/core/auth/ee' class MyFGAProvider implements IFGAProvider { // ...check, require, filterAccessible... async requireActor(actor: ActorSignal, params: FGACheckParams): Promise { const agentId = actor === true ? undefined : actor.agentId // Resolve the agent's real grants from a trusted source keyed by agentId. const granted = await this.grantsForAgent(agentId) const required = Array.isArray(params.permission) ? params.permission : [params.permission] if (!required.some(permission => granted.includes(permission))) { throw new FGADeniedError(null, params.resource, params.permission) } } } ``` ### Exigences de confiance Le signal d'acteur est une entrée de confiance ; construisez-le donc côté serveur : - Traitez `actor` comme un signal propre à chaque appel. Les workflows durables le transmettent au démarrage d'une exécution, mais ne rétablissent pas l'acteur initial lors d'une reprise. Transmettez-le explicitement à chaque reprise de confiance, ou déterminez un nouvel acteur à l'aide des `defaultOptions` de l'agent. En l'absence d'acteur actuel, l'autorisation utilisateur s'applique et l'absence d'utilisateur entraîne un refus par défaut. - Mastra retire `actor` des options d'exécution prises en charge par ses routes HTTP intégrées pour les agents. Définissez-le dans le code côté serveur, par exemple dans une tâche planifiée ou un workflow, et jamais à partir d'une entrée client. - Établissez la portée du tenant côté serveur. Les routes HTTP intégrées des agents ignorent tout `organizationId` fourni par le client dans le contexte de requête, et le chemin d'un acteur de confiance exige qu'un `organizationId` soit défini. - La reprise durable conserve son comportement actuel de récupération et de fusion du contexte de requête. Cela ne rend pas un acteur persistant digne de confiance pour un segment ultérieur du workflow. - Le contrôle de la portée du tenant confirme l'existence d'un `organizationId` de confiance. Il ne vérifie pas que `actor.agentId` appartient à cette organisation. Lorsque cette relation est importante, vérifiez-la dans `requireActor` à l'aide des données de référence du fournisseur. - Considérez `actor.permissions` comme une déclaration non vérifiée. Déterminez les autorisations de référence à partir d'une source de confiance. Un fournisseur qui applique le principe du moindre privilège récupère les autorisations de référence de l'agent auprès d'une source fiable, par exemple un manifeste ou votre backend FGA indexé par `agentId`, au lieu de faire confiance aux valeurs fournies directement. - Dès qu'un fournisseur implémente `requireActor`, les erreurs levées par cette méthode interrompent l'exécution. Mastra ne se rabat pas sur une autorisation limitée à l'organisation. ## Ressources associées - [Référence de `IFGAProvider`](https://mastra.zisheng.pro/fr/reference/auth/fga) - [Vue d'ensemble de l'authentification](https://mastra.zisheng.pro/fr/docs/server/auth) - [Authentification avec WorkOS](https://mastra.zisheng.pro/fr/docs/server/auth/workos)