본문으로 건너뛰기

FGA(세밀한 권한 부여)

:::참고 세분화된 인증은 Mastra Enterprise Edition의 일부입니다. 프로덕션 배포에는 유효한 EE 라이선스가 필요합니다.Contact sales자세한 내용은 :::

FGA(Fine-Grained Authorization)는 Mastra 애플리케이션에 리소스 수준의 권한 검사를 추가합니다. RBAC가 "이 역할이 이 작업을 수행할 수 있는가?"에 답한다면, FGA는 **"이 사용자가 이 특정 리소스에 대해 이 작업을 수행할 수 있는가?"**에 답합니다.

FGA를 사용하는 경우
FGA를 사용하는 경우에 대한 직접 링크

FGA는 권한이 상황에 맞는 다중 테넌트 B2B 제품을 위해 설계되었습니다.

  • 사용자는 Team A의 admin이지만 Team B에서는 member일 수 있습니다.
  • 스레드 액세스는 사용자가 속한 조직으로 제한해야 합니다.
  • Workflow 실행 범위는 특정 팀 또는 프로젝트로 제한해야 합니다.
  • Tool 액세스 권한은 사용자와 리소스 간의 관계에 따라 달라질 수 있습니다.

구성
구성에 대한 직접 링크

인증 및 RBAC와 함께 Mastra 서버 구성에서 FGA를 구성합니다.

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 검사가 권한 부여에 적합한 멤버십 ID를 확인하려면 사용자의 조직 멤버십이 필요합니다. Memory 권한 부여의 리소스 매핑 키로 thread를 사용하세요. MastraFGAWorkos는 기존 별칭인 memory도 계속 허용하지만, 새 구성에서는 thread를 사용하는 것이 좋습니다. server.fga가 구성되어 있으면 Mastra는 보호되는 작업에 FGA를 적용합니다. 보호되는 작업에 인증된 사용자가 없으면 Mastra가 해당 작업을 거부합니다. server.fga가 구성되어 있지 않으면 이러한 FGA 검사를 건너뛰고 Mastra의 이전 동작을 유지합니다.

리소스 매핑
리소스 매핑에 대한 직접 링크

resourceMapping은 요청 컨텍스트에서 FGA 리소스 유형과 ID를 확인하는 방법을 Mastra에 알려 줍니다. 키는 Mastra 리소스 유형이며, 값은 FGA 리소스 유형과 ID를 도출하는 방법을 정의합니다.

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(예: 스레드의resourceId)
  • requestContext: 고급 테넌트 확인을 위한 현재 요청 컨텍스트
  • metadata: 시도한 작업에 대한 공급자별 메타데이터

deriveId()에서 undefined를 반환하면 원래 Mastra 리소스 ID를 사용합니다. 스레드 및 Memory 검사에서 Mastra는 검사할 리소스로 원시 threadId를 계속 전달하지만, 스레드를 소유한 resourceIdderiveId()에 전달합니다. 따라서 스레드 권한을 userId-teamId-orgId 같은 복합 테넌트 ID에 매핑할 수 있습니다.

권한 매핑
권한 매핑에 대한 직접 링크

permissionMapping은 Mastra 내부 권한 문자열을 FGA Provider의 권한 슬러그로 변환합니다.

import { MastraFGAPermissions } from '@mastra/core/auth/ee';

permissionMapping: {
[MastraFGAPermissions.AGENTS_EXECUTE]: 'manage-workflows', // Mastra permission -> WorkOS permission slug
[MastraFGAPermissions.MEMORY_READ]: 'read',
}

권한에 대한 매핑이 없으면 원래 문자열이 전달됩니다.

validatePermissions()를 사용하면 Mastra가 시작 시 내보낼 수 있는 전체 권한 집합을 검증할 수 있습니다. 모든 Mastra 권한에 명시적인 Provider 권한 슬러그가 필요한 Provider에서는 이 메서드를 사용하세요.

저장된 리소스 범위 지정
저장된 리소스 범위 지정에 대한 직접 링크

FGA는 리소스에 대한 액세스를 승인합니다. 공유 저장소에 있는 저장된 기록은 자동으로 필터링되지 않습니다. 내장된 저장 리소스 API가 다중 테넌트 앱에서 사용되는 경우 저장 리소스 범위 지정을 활성화합니다.

const mastra = new Mastra({
server: {
auth: new MastraAuthWorkos({
/* ... */
mapUserToResourceId: user => user.teamId,
}),
storedResources: {
scope: true,
},
},
});

scope: true를 설정하면 Mastra는 요청 컨텍스트에서 MASTRA_RESOURCE_ID_KEY를 읽습니다. mapUserToResourceId()는 인증 후 이 값을 설정합니다. 저장된 리소스 핸들러는 레코드 메타데이터에 범위를 유지하고 목록 조회, 읽기, 업데이트, 게시 및 삭제 작업을 해당 범위로 필터링합니다. 범위에 사용자 정의 요청 논리가 필요한 경우 객체를 사용하십시오.

storedResources: {
scope: {
metadataKey: 'teamId',
resolve: ({ user }) => user.teamId,
requireScope: true,
},
},

requireScopetrue이거나 생략된 경우, 범위를 확인할 수 없으면 범위가 지정된 저장 리소스 경로가 실패합니다.

경로 정책 적용 범위
경로 정책 적용 범위에 대한 직접 링크

Mastra에는 Agent, Workflow, Tool, MCP Tool, Memory 스레드, 응답, 대화 및 저장된 리소스를 포함하는 기본 제공 리소스 경로에 대한 경로 수준 FGA 메타데이터가 포함되어 있습니다. 저장된 리소스 경로 범위에는 /stored/agents, /stored/mcp-clients, /stored/prompt-blocks, /stored/scorers, /stored/skills, /stored/workspaces가 포함됩니다. 경로 수준 fga 메타데이터가 있거나, Mastra가 해당 경로의 기본 제공 메타데이터를 도출할 수 있거나, Provider가 resolveRouteFGA()로 메타데이터를 제공하면 경로를 검사합니다. FGA 메타데이터를 확인하지 않는 보호된 경로를 거부하려면 FGA 공급자에서 경로 정책 적용 범위를 구성합니다.

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.
},
});

보호되는 경로에 기본 제공 FGA 메타데이터가 없을 때 시작을 실패 처리하려면 auditProtectedRoutes: 'error'를 설정하세요. requireForProtectedRoutes가 활성화되어 있으면 Mastra는 기본적으로 이 감사 결과를 경고로 기록합니다. 사용자 지정 경로에서는 경로 수준의 fga 메타데이터를 사용하는 것이 좋습니다. 그러면 권한 부여 정책을 경로와 함께 둘 수 있습니다.

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 };
},
});

경로, 매개변수 또는 요청 컨텍스트에서 경로 메타데이터를 중앙 집중식으로 도출해야 할 때만 resolveRouteFGA()를 사용하세요. 경로 맵은 문자열 접두사 검사보다 확장성이 뛰어납니다.

import type { FGARouteConfig, FGARouteResolver } from '@mastra/core/auth/ee';

const routeFGA = {
'GET /billing/:accountId': {
resourceType: 'account',
resourceIdParam: 'accountId',
permission: 'billing:read',
},
} satisfies Record<string, FGARouteConfig>;

const resolveRouteFGA: FGARouteResolver = ({ route }) => routeFGA[`${route.method} ${route.path}`];

const fga = new MastraFGAWorkos({
/* ... */
resolveRouteFGA,
});

시행 포인트
시행 포인트에 대한 직접 링크

FGA 공급자가 구성되면 Mastra는 다음 수명 주기 지점에서 자동으로 인증을 확인합니다.

수명 주기 지점검사하는 권한리소스 유형리소스 ID
Agent 실행(generate, stream)agents:executeagentagentId
기본 제공 Workflow HTTP 실행 경로 및 Workflow.execute()workflows:executeworkflowworkflowId
독립형 Tool 실행tools:executetooltoolName
Agent Tool 실행tools:executetool${agentId}:${toolName}
MCP Tool 실행tools:execute기본적으로 tool, 또는 서버 수준 fga.resourceMapping 재정의 값기본적으로 JSON.stringify([serverName, toolName]), 또는 서버 수준에서 도출한 ID
스레드 및 Memory 액세스memory:read, memory:write, memory:deletethreadthreadId
저장된 리소스 경로경로 작업에 해당하는 저장된 리소스 권한저장된 리소스 유형경로 레코드 ID 또는 컬렉션 경로의 저장된 리소스 범위
HTTP 리소스 경로경로별로 구성경로별로 구성경로별로 구성
OAuth로 보호되는 MCP 서버의 경우 HTTP MCP 전송은 인증된 데이터를 extra.authInfo로 전달합니다. FGA가 활성화된 Mastra 인스턴스에 MCPServer를 등록하는 경우, Mastra가 tools/listtools/call을 검사하기 전에 requestContext.get('user')를 설정할 수 있도록 mapAuthInfoToUser를 구성하세요. MCP Tool 검사에 내부 Agent 및 Workflow Tool 검사와 다른 리소스 또는 권한 매핑이 필요한 경우 서버 수준의 fga 옵션을 사용하세요. MCPServer 인증 컨텍스트를 참조하세요.
직접 SDK로 호출하는 createRun().start(), resume(), restart()는 이번 릴리스에서 Core FGA가 개별적으로 검사하지 않습니다. 이러한 호출은 보호되는 경로에서 실행하거나 애플리케이션 코드에서 보호하세요. 보호되는 진입점을 직접 호출할 때는 인증된 사용자가 포함된 requestContext를 전달하세요.
핵심 Agent, 내부 Workflow, Tool 및 Memory 검사도 requestContext와 작업 메타데이터를 FGA Provider에 전달합니다. 경로 검사는 requestContext를 전달합니다. 스레드 검사는 가능한 경우 소유자의 resourceId를 전달합니다.

맞춤형 FGA 공급자
맞춤형 FGA 공급자에 대한 직접 링크

FGA 백엔드를 사용하려면 IFGAProvider를 구현하세요.

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<boolean> {
// Your authorization logic
return true
}

async require(user: any, params: FGACheckParams): Promise<void> {
const allowed = await this.check(user, params)
if (!allowed) {
throw new FGADeniedError(user, params.resource, params.permission)
}
}

async filterAccessible<T extends { id: string }>(
user: any,
resources: T[],
resourceType: string,
permission: MastraFGAPermissionInput,
): Promise<T[]> {
// Filter resources the user can access
return resources
}
}

:::참고 모든 메서드와 매개변수 및 ActorSignal 유형은 IFGAProvider 레퍼런스를 참조하세요. :::

시스템 액터
시스템 액터에 대한 직접 링크

자율 및 예약 Agent는 최종 사용자 없이 실행됩니다. FGA가 사용자 요청과 구별할 수 있도록 이러한 호출을 행위자 신호로 표시합니다.

  • true 또는 { actorKind: 'system' }은 익명 시스템 행위자를 나타냅니다.
  • 객체 형태에는 행위하는 Agent를 식별하고 제한하기 위한 agentId, permissions, scope도 포함할 수 있습니다. 기본적으로 신뢰할 수 있는 행위자는 테넌트 범위 검사 후 사용자 중심의 require() 검사를 건너뜁니다. Agent별 최소 권한을 적용하려면 Provider에서 선택적 requireActor 메서드를 구현하세요. 이 메서드는 행위자와 require에 전달되는 것과 동일한 FGACheckParams를 받고, 거부하려면 FGADeniedError를 발생시킵니다. Provider가 requireActor를 구현하지 않으면 신뢰할 수 있는 행위자의 우회 동작이 유지되므로 이를 추가해도 이전 버전과 호환됩니다.
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<void> {
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는 호출별 신호로 취급하세요. 내구성 있는 Workflow는 실행이 시작될 때 이를 전달하지만, 재개할 때 최초 행위자를 복원하지는 않습니다. 신뢰할 수 있는 재개 작업마다 이를 명시적으로 전달하거나 Agent defaultOptions를 통해 새로운 행위자를 확인하세요. 현재 행위자가 없으면 사용자 권한 부여가 적용되며 사용자가 없을 경우 안전하게 실패합니다.
  • Mastra는 기본 제공 Agent HTTP 경로가 처리하는 실행 옵션에서 actor를 제거합니다. 클라이언트 입력이 아니라 예약 작업이나 Workflow 같은 서버 측 코드에서 설정하세요.
  • 테넌트 범위는 서버 측에서 설정하세요. 기본 제공 Agent HTTP 경로는 요청 컨텍스트에서 클라이언트가 제공한 organizationId를 무시하며, 신뢰할 수 있는 행위자 경로를 사용하려면 organizationId가 설정되어 있어야 합니다.
  • 내구성 있는 재개는 기존의 요청 컨텍스트 복원 및 병합 동작을 유지합니다. 그렇다고 이후 Workflow 세그먼트에서 지속된 행위자를 신뢰할 수 있게 되는 것은 아닙니다.
  • 테넌트 범위 검사는 신뢰할 수 있는 organizationId가 있는지 확인합니다. actor.agentId가 해당 조직에 속하는지는 확인하지 않습니다. 이 관계가 중요하다면 신뢰할 수 있는 Provider 데이터를 사용하여 requireActor에서 확인하세요.
  • actor.permissions는 검증되지 않은 클레임으로 취급하세요. 신뢰할 수 있는 소스에서 권한을 확인하세요. 최소 권한을 적용하는 Provider는 인라인 값을 신뢰하는 대신 매니페스트나 agentId를 키로 사용하는 FGA 백엔드 같은 신뢰할 수 있는 소스에서 Agent의 권한을 확인합니다.
  • Provider가 requireActor를 구현한 경우 해당 메서드의 오류는 실행을 중단합니다. Mastra는 조직만을 기준으로 한 권한 부여로 대체하지 않습니다.