> Discover all available pages from the documentation index: https://mastra.zisheng.pro/zh-TW/llms.txt # 細粒度授權(FGA) > **備註:** 細粒度授權是 Mastra Enterprise Edition 的一部分。正式環境部署需要有效的 EE 授權。如需更多資訊,請[聯絡業務團隊](https://mastra.ai/contact)。 細粒度授權(FGA)會為 Mastra 應用程式加入資源層級的權限檢查。RBAC 回答的是「這個角色能否執行此動作?」,FGA 回答的則是\*\*「這位使用者能否對這個特定資源執行此動作?」\*\* ## 適合使用 FGA 的情況 FGA 專為權限取決於情境的多租戶 B2B 產品而設計: - 使用者可能是團隊 A 的**管理員**,但只是團隊 B 的**成員** - Thread 存取權應限於使用者自己的組織 - Workflow 執行應限於特定團隊或專案 - Tool 存取權取決於使用者與資源的關係 ## 設定 在 Mastra 伺服器設定中,將 FGA 與驗證及 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, }, }, }); ``` 使用 `MastraFGAWorkos` 時,請在 `MastraAuthWorkos` 上設定 `fetchMemberships: true`。WorkOS FGA 檢查需要使用者的 organization membership,才能解析授權所需的正確 membership ID。 進行 memory 授權時,請使用 `thread` 作為資源對應 key。`MastraFGAWorkos` 仍接受舊版別名 `memory`,但新設定應優先使用 `thread`。 設定 `server.fga` 後,Mastra 會對受保護動作強制執行 FGA。若受保護動作沒有已驗證的使用者,Mastra 會拒絕該動作。若未設定 `server.fga`,則會略過這些 FGA 檢查,Mastra 會維持先前的行為。 ### 資源對應 `resourceMapping` 會告訴 Mastra 如何從 request context 解析 FGA 資源類型與 ID。Key 是 Mastra 資源類型,value 則定義 FGA 資源類型及 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()` 會接收: - `user`:已驗證的使用者 - `resourceId`:可用時,所屬 Mastra 資源的 ID(例如 thread 的 `resourceId`) - `requestContext`:用於進階 tenant 解析的目前 request context - `metadata`:嘗試執行之動作的 Provider 特定 metadata 從 `deriveId()` 傳回 `undefined`,即可改用原始 Mastra 資源 ID。 進行 thread 與 memory 檢查時,Mastra 仍會將原始 `threadId` 作為受檢查資源傳入,但也會將 thread 所屬的 `resourceId` 轉送至 `deriveId()`。因此,你可以將 thread 權限對應至 `userId-teamId-orgId` 等複合 tenant ID。 ### 權限對應 `permissionMapping` 會將 Mastra 的內部權限字串轉換為 FGA Provider 的權限 slug: ```typescript import { MastraFGAPermissions } from '@mastra/core/auth/ee'; permissionMapping: { [MastraFGAPermissions.AGENTS_EXECUTE]: 'manage-workflows', // Mastra permission -> WorkOS permission slug [MastraFGAPermissions.MEMORY_READ]: 'read', } ``` 若權限沒有對應項目,系統會直接傳入原始字串。 使用 `validatePermissions()`,在啟動時驗證 Mastra 可能發出的完整權限集合。當 Provider 要求每項 Mastra 權限都必須具有明確的 Provider 權限 slug 時,請使用此方法。 ### 儲存資源的 scope FGA 會授權資源存取,但不會自動篩選位於共用儲存空間的已儲存記錄。在多租戶應用程式中使用內建的已儲存資源 API 時,請啟用已儲存資源的 scope。 ```typescript const mastra = new Mastra({ server: { auth: new MastraAuthWorkos({ /* ... */ mapUserToResourceId: user => user.teamId, }), storedResources: { scope: true, }, }, }); ``` 設定 `scope: true` 後,Mastra 會從 request context 讀取 `MASTRA_RESOURCE_ID_KEY`。`mapUserToResourceId()` 會在驗證後設定此值。已儲存資源 handler 會將 scope 保存於記錄 metadata,並依該 scope 篩選列出、讀取、更新、發布與刪除操作。 當 scope 需要自訂請求邏輯時,請使用物件: ```typescript storedResources: { scope: { metadataKey: 'teamId', resolve: ({ user }) => user.teamId, requireScope: true, }, }, ``` 若 `requireScope` 為 `true` 或省略,當無法解析 scope 時,具 scope 的已儲存資源 route 會失敗。 ### Route policy 涵蓋範圍 Mastra 為內建資源 route 提供 route 層級的 FGA metadata,涵蓋 Agent、Workflow、Tool、MCP Tool、memory thread、response、conversation 與已儲存資源。已儲存資源 route 涵蓋 `/stored/agents`、`/stored/mcp-clients`、`/stored/prompt-blocks`、`/stored/scorers`、`/stored/skills` 與 `/stored/workspaces`。當 route 具有 route 層級的 `fga` metadata、Mastra 可為該 route 衍生內建 metadata,或 Provider 透過 `resolveRouteFGA()` 提供 metadata 時,系統就會檢查該 route。 若要拒絕無法解析 FGA metadata 的受保護 route,請在 FGA Provider 上設定 route policy 涵蓋範圍: ```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. }, }); ``` 將 `auditProtectedRoutes: 'error'` 設為在受保護 route 缺少內建 FGA metadata 時,讓啟動失敗。若啟用 `requireForProtectedRoutes`,Mastra 預設會將此稽核記錄為警告。 針對自訂 route,請優先使用 route 層級的 `fga` metadata。這能讓授權 policy 與 route 放在一起: ```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 }; }, }); ``` 只有在必須集中依 route、params 或 request context 衍生 route metadata 時,才使用 `resolveRouteFGA()`。Route map 比字串前綴檢查更容易擴充: ```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, }); ``` ## 強制執行點 設定 FGA Provider 後,Mastra 會在下列生命週期節點自動檢查授權: | 生命週期節點 | 檢查的權限 | 資源類型 | 資源 ID | | ------------------------------------------------ | -------------------------------------------- | -------------------------------------------- | --------------------------------------------------------- | | Agent 執行(`generate`、`stream`) | `agents:execute` | `agent` | `agentId` | | 內建 Workflow HTTP 執行 route 與 `Workflow.execute()` | `workflows:execute` | `workflow` | `workflowId` | | 獨立 Tool 執行 | `tools:execute` | `tool` | `toolName` | | Agent Tool 執行 | `tools:execute` | `tool` | `${agentId}:${toolName}` | | MCP Tool 執行 | `tools:execute` | 預設為 `tool`,或伺服器層級的 `fga.resourceMapping` 覆寫值 | 預設為 `JSON.stringify([serverName, toolName])`,或伺服器層級衍生的 ID | | Thread 與 memory 存取 | `memory:read`、`memory:write`、`memory:delete` | `thread` | `threadId` | | 已儲存資源 route | Route 動作的已儲存資源權限 | 已儲存資源類型 | Route 記錄 ID,或 collection route 的已儲存資源 scope | | HTTP 資源 route | 依 route 設定 | 依 route 設定 | 依 route 設定 | 對於受 OAuth 保護的 MCP 伺服器,HTTP MCP transport 會將已驗證資料以 `extra.authInfo` 傳入。若在已啟用 FGA 的 Mastra 執行個體上註冊 `MCPServer`,請設定 `mapAuthInfoToUser`,讓 Mastra 能在檢查 `tools/list` 與 `tools/call` 前設定 `requestContext.get('user')`。當 MCP Tool 檢查需要與內部 Agent 及 Workflow Tool 檢查不同的資源或權限對應時,請使用伺服器層級的 `fga` 選項。請參閱 [MCPServer 驗證 context](https://mastra.zisheng.pro/zh-TW/reference/tools/mcp-server)。 在此版本中,直接呼叫 SDK 的 `createRun().start()`、`resume()` 或 `restart()` 不會由核心 FGA 個別檢查。請從受保護 route 呼叫這些方法,或在應用程式程式碼中加以防護。直接叫用受保護 entry point 時,請傳入包含已驗證使用者的 `requestContext`。 核心 Agent、內部 Workflow、Tool 與 memory 檢查也會將 `requestContext` 和動作 metadata 傳給 FGA Provider。Route 檢查會傳入 `requestContext`。Thread 檢查會在可用時傳入所屬的 `resourceId`。 ## 自訂 FGA Provider 實作 `IFGAProvider` 以使用任何 FGA backend: ```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 } } ``` > **備註:** 如需所有方法、參數與 `ActorSignal` 類型的說明,請參閱 [`IFGAProvider` 參考文件](https://mastra.zisheng.pro/zh-TW/reference/auth/fga)。 ## 系統 actor 自主與排程的 Agent 會在沒有終端使用者的情況下執行。請使用 actor signal 標記這些呼叫,讓 FGA 能將其與使用者請求區分: - `true` 或 `{ actorKind: 'system' }` 代表匿名系統 actor。 - 物件形式也可以包含 `agentId`、`permissions` 與 `scope`,以識別並限制執行動作的 Agent。 受信任 actor 預設會在 tenant scope 檢查後略過以使用者為中心的 `require()` 檢查。若要強制每個 Agent 遵循最小權限原則,請在 Provider 上實作選用的 `requireActor` 方法。此方法會接收 actor 與 `require` 所接收的相同 `FGACheckParams`,並擲回 `FGADeniedError` 以拒絕操作。Provider 未實作 `requireActor` 時,系統會保留受信任 actor 的略過行為,因此加入此方法可向後相容。 ```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) } } } ``` ### 信任需求 Actor signal 是受信任的輸入,因此請在伺服器端建立: - 將 `actor` 視為每次呼叫各自的 signal。Durable Workflow 會在執行開始時轉送該值,但不會在繼續執行時還原初始 actor。每次受信任的繼續執行都應明確傳入該值,或透過 Agent `defaultOptions` 解析新的 actor。若沒有目前 actor,則會套用使用者授權,而缺少使用者時會以拒絕方式安全失敗。 - Mastra 會從內建 Agent HTTP route 所處理的執行選項中移除 `actor`。請在伺服器端程式碼中設定,例如排程工作或 Workflow,切勿使用用戶端輸入。 - 在伺服器端建立 tenant scope。內建 Agent HTTP route 會忽略用戶端在 request context 中提供的 `organizationId`,且受信任 actor 路徑要求必須設定 `organizationId`。 - Durable resume 會保留既有的 request context 復原與合併行為。這不會讓保存的 actor 在後續 Workflow 區段中成為受信任的 actor。 - Tenant scope 檢查會確認受信任的 `organizationId` 存在,但不會驗證 `actor.agentId` 是否屬於該組織。當此關係很重要時,請在 `requireActor` 中使用權威的 Provider 資料進行驗證。 - 將 `actor.permissions` 視為未驗證的 claim。請從受信任來源解析權威 grant。強制執行最小權限的 Provider 會從受信任來源解析 Agent 的權威權限,例如以 `agentId` 為 key 的 manifest 或 FGA backend,而不是信任 inline value。 - Provider 一旦實作 `requireActor`,該方法發生錯誤時便會停止執行。Mastra 不會退回僅限組織的授權。 ## 相關內容 - [`IFGAProvider` 參考文件](https://mastra.zisheng.pro/zh-TW/reference/auth/fga) - [驗證概觀](https://mastra.zisheng.pro/zh-TW/docs/server/auth) - [WorkOS 驗證](https://mastra.zisheng.pro/zh-TW/docs/server/auth/workos)