Approval plugin for FrontMCP - tool authorization workflow with PKCE webhook security
npm install @frontmcp/plugin-approvalTool authorization workflow with PKCE webhook security for FrontMCP.
- Tool Approval Checking: Automatic approval check before tool execution via hook
- Multiple Approval Scopes: SESSION, USER, TIME_LIMITED, TOOL_SPECIFIC, CONTEXT_SPECIFIC
- PKCE Webhook Security: RFC 7636 compliant PKCE for secure external approval systems
- Recheck Mode: Poll external API for approval status
- Full Audit Trail: Track who approved/revoked and when
- Context Extension: Use this.approval in tools
``bash`
npm install @frontmcp/plugin-approval
`typescript
import { ApprovalPlugin } from '@frontmcp/plugin-approval';
// Create plugin with default settings
const plugin = ApprovalPlugin.init();
// Install into scope
await plugin.install(scope);
`
`typescript`
const plugin = ApprovalPlugin.init({
mode: 'webhook',
webhook: {
url: 'https://approval.example.com/webhook',
challengeTtl: 300, // 5 minutes
callbackPath: '/approval/callback',
},
});
`typescript
import { Tool, ToolContext } from '@frontmcp/sdk';
@Tool({
name: 'dangerous_operation',
approval: {
required: true,
defaultScope: 'session',
category: 'write',
riskLevel: 'high',
approvalMessage: 'Allow dangerous operation?',
},
})
class DangerousTool extends ToolContext {
async execute() {
// This tool requires approval before execution
// The approval hook automatically checks and throws ApprovalRequiredError if needed
// You can also programmatically check/grant approvals:
const approved = await this.approval.isApproved('other-tool');
await this.approval.grantSessionApproval('helper-tool');
}
}
`
| Scope | Description |
| ------------------ | ------------------------------------------- |
| SESSION | Valid for current session only |USER
| | Persists across sessions for the user |TIME_LIMITED
| | Expires after specified TTL |TOOL_SPECIFIC
| | Specific to a particular tool |CONTEXT_SPECIFIC
| | Specific to a context (repo, project, etc.) |
`typescript
interface ApprovalPluginOptions {
// Storage configuration
storage?: StorageConfig;
storageInstance?: RootStorage | NamespacedStorage;
namespace?: string; // default: 'approval'
// Approval mode
mode?: 'recheck' | 'webhook'; // default: 'recheck'
// Recheck mode options
recheck?: {
url?: string;
auth?: 'jwt' | 'bearer' | 'none' | 'custom';
interval?: number;
maxAttempts?: number;
};
// Webhook mode options
webhook?: {
url?: string;
includeJwt?: boolean; // default: false (security)
challengeTtl?: number; // seconds, default: 300
callbackPath?: string; // default: '/approval/callback'
};
// Audit options
enableAudit?: boolean; // default: true
maxDelegationDepth?: number; // default: 3
cleanupIntervalSeconds?: number; // default: 60
}
`
When using webhook mode, ApprovalPlugin uses PKCE (RFC 7636) for secure authorization:
1. Generate PKCE pair: code_verifier (secret) + code_challenge (hash)challenge:{code_challenge}
2. Store challenge in Redis: → session info{code_challenge, toolId, callbackUrl}
3. Send to webhook: (NO session ID!)POST /approval/callback {code_verifier, approved}
4. External system calls back: SHA256(code_verifier) === stored code_challenge
5. Plugin validates:
6. Grant approval if valid
This ensures:
- Session ID is never exposed to external systems
- Challenge is single-use (deleted after callback)
- Challenge expires after TTL
- Only holder of code_verifier` can complete approval
Apache-2.0