@nitrostack/core 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +80 -0
- package/dist/auth/api-key.d.ts +118 -0
- package/dist/auth/api-key.d.ts.map +1 -0
- package/dist/auth/api-key.js +168 -0
- package/dist/auth/api-key.js.map +1 -0
- package/dist/auth/client.d.ts +151 -0
- package/dist/auth/client.d.ts.map +1 -0
- package/dist/auth/client.js +330 -0
- package/dist/auth/client.js.map +1 -0
- package/dist/auth/index.d.ts +31 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +46 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/middleware.d.ts +95 -0
- package/dist/auth/middleware.d.ts.map +1 -0
- package/dist/auth/middleware.js +260 -0
- package/dist/auth/middleware.js.map +1 -0
- package/dist/auth/pkce.d.ts +53 -0
- package/dist/auth/pkce.d.ts.map +1 -0
- package/dist/auth/pkce.js +105 -0
- package/dist/auth/pkce.js.map +1 -0
- package/dist/auth/quick-setup.d.ts +94 -0
- package/dist/auth/quick-setup.d.ts.map +1 -0
- package/dist/auth/quick-setup.js +210 -0
- package/dist/auth/quick-setup.js.map +1 -0
- package/dist/auth/secure-secret.d.ts +136 -0
- package/dist/auth/secure-secret.d.ts.map +1 -0
- package/dist/auth/secure-secret.js +182 -0
- package/dist/auth/secure-secret.js.map +1 -0
- package/dist/auth/server-integration.d.ts +97 -0
- package/dist/auth/server-integration.d.ts.map +1 -0
- package/dist/auth/server-integration.js +182 -0
- package/dist/auth/server-integration.js.map +1 -0
- package/dist/auth/server-metadata.d.ts +51 -0
- package/dist/auth/server-metadata.d.ts.map +1 -0
- package/dist/auth/server-metadata.js +106 -0
- package/dist/auth/server-metadata.js.map +1 -0
- package/dist/auth/simple-jwt.d.ts +174 -0
- package/dist/auth/simple-jwt.d.ts.map +1 -0
- package/dist/auth/simple-jwt.js +162 -0
- package/dist/auth/simple-jwt.js.map +1 -0
- package/dist/auth/token-store.d.ts +104 -0
- package/dist/auth/token-store.d.ts.map +1 -0
- package/dist/auth/token-store.js +205 -0
- package/dist/auth/token-store.js.map +1 -0
- package/dist/auth/token-validation.d.ts +59 -0
- package/dist/auth/token-validation.d.ts.map +1 -0
- package/dist/auth/token-validation.js +241 -0
- package/dist/auth/token-validation.js.map +1 -0
- package/dist/auth/types.d.ts +215 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +6 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/core/apikey-module.d.ts +69 -0
- package/dist/core/apikey-module.d.ts.map +1 -0
- package/dist/core/apikey-module.js +114 -0
- package/dist/core/apikey-module.js.map +1 -0
- package/dist/core/app-decorator.d.ts +59 -0
- package/dist/core/app-decorator.d.ts.map +1 -0
- package/dist/core/app-decorator.js +322 -0
- package/dist/core/app-decorator.js.map +1 -0
- package/dist/core/builders.d.ts +50 -0
- package/dist/core/builders.d.ts.map +1 -0
- package/dist/core/builders.js +139 -0
- package/dist/core/builders.js.map +1 -0
- package/dist/core/component.d.ts +111 -0
- package/dist/core/component.d.ts.map +1 -0
- package/dist/core/component.js +228 -0
- package/dist/core/component.js.map +1 -0
- package/dist/core/config-module.d.ts +62 -0
- package/dist/core/config-module.d.ts.map +1 -0
- package/dist/core/config-module.js +94 -0
- package/dist/core/config-module.js.map +1 -0
- package/dist/core/decorators/cache.decorator.d.ts +61 -0
- package/dist/core/decorators/cache.decorator.d.ts.map +1 -0
- package/dist/core/decorators/cache.decorator.js +115 -0
- package/dist/core/decorators/cache.decorator.js.map +1 -0
- package/dist/core/decorators/health-check.decorator.d.ts +80 -0
- package/dist/core/decorators/health-check.decorator.d.ts.map +1 -0
- package/dist/core/decorators/health-check.decorator.js +153 -0
- package/dist/core/decorators/health-check.decorator.js.map +1 -0
- package/dist/core/decorators/rate-limit.decorator.d.ts +63 -0
- package/dist/core/decorators/rate-limit.decorator.d.ts.map +1 -0
- package/dist/core/decorators/rate-limit.decorator.js +129 -0
- package/dist/core/decorators/rate-limit.decorator.js.map +1 -0
- package/dist/core/decorators.d.ts +190 -0
- package/dist/core/decorators.d.ts.map +1 -0
- package/dist/core/decorators.js +170 -0
- package/dist/core/decorators.js.map +1 -0
- package/dist/core/di/container.d.ts +64 -0
- package/dist/core/di/container.d.ts.map +1 -0
- package/dist/core/di/container.js +105 -0
- package/dist/core/di/container.js.map +1 -0
- package/dist/core/di/injectable.decorator.d.ts +62 -0
- package/dist/core/di/injectable.decorator.d.ts.map +1 -0
- package/dist/core/di/injectable.decorator.js +66 -0
- package/dist/core/di/injectable.decorator.js.map +1 -0
- package/dist/core/errors.d.ts +54 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +87 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/events/event-emitter.d.ts +50 -0
- package/dist/core/events/event-emitter.d.ts.map +1 -0
- package/dist/core/events/event-emitter.js +94 -0
- package/dist/core/events/event-emitter.js.map +1 -0
- package/dist/core/events/event.decorator.d.ts +48 -0
- package/dist/core/events/event.decorator.d.ts.map +1 -0
- package/dist/core/events/event.decorator.js +72 -0
- package/dist/core/events/event.decorator.js.map +1 -0
- package/dist/core/events/log-emitter.d.ts +14 -0
- package/dist/core/events/log-emitter.d.ts.map +1 -0
- package/dist/core/events/log-emitter.js +20 -0
- package/dist/core/events/log-emitter.js.map +1 -0
- package/dist/core/filters/exception-filter.decorator.d.ts +40 -0
- package/dist/core/filters/exception-filter.decorator.d.ts.map +1 -0
- package/dist/core/filters/exception-filter.decorator.js +54 -0
- package/dist/core/filters/exception-filter.decorator.js.map +1 -0
- package/dist/core/filters/exception-filter.interface.d.ts +39 -0
- package/dist/core/filters/exception-filter.interface.d.ts.map +1 -0
- package/dist/core/filters/exception-filter.interface.js +2 -0
- package/dist/core/filters/exception-filter.interface.js.map +1 -0
- package/dist/core/guards/apikey.guard.d.ts +22 -0
- package/dist/core/guards/apikey.guard.d.ts.map +1 -0
- package/dist/core/guards/apikey.guard.js +11 -0
- package/dist/core/guards/apikey.guard.js.map +1 -0
- package/dist/core/guards/guard.interface.d.ts +18 -0
- package/dist/core/guards/guard.interface.d.ts.map +1 -0
- package/dist/core/guards/guard.interface.js +2 -0
- package/dist/core/guards/guard.interface.js.map +1 -0
- package/dist/core/guards/jwt.guard.d.ts +18 -0
- package/dist/core/guards/jwt.guard.d.ts.map +1 -0
- package/dist/core/guards/jwt.guard.js +2 -0
- package/dist/core/guards/jwt.guard.js.map +1 -0
- package/dist/core/guards/oauth.guard.d.ts +35 -0
- package/dist/core/guards/oauth.guard.d.ts.map +1 -0
- package/dist/core/guards/oauth.guard.js +2 -0
- package/dist/core/guards/oauth.guard.js.map +1 -0
- package/dist/core/guards/use-guards.decorator.d.ts +25 -0
- package/dist/core/guards/use-guards.decorator.d.ts.map +1 -0
- package/dist/core/guards/use-guards.decorator.js +32 -0
- package/dist/core/guards/use-guards.decorator.js.map +1 -0
- package/dist/core/health/health-checks.resource.d.ts +14 -0
- package/dist/core/health/health-checks.resource.d.ts.map +1 -0
- package/dist/core/health/health-checks.resource.js +29 -0
- package/dist/core/health/health-checks.resource.js.map +1 -0
- package/dist/core/index.d.ts +57 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +59 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/interceptors/interceptor.decorator.d.ts +37 -0
- package/dist/core/interceptors/interceptor.decorator.d.ts.map +1 -0
- package/dist/core/interceptors/interceptor.decorator.js +51 -0
- package/dist/core/interceptors/interceptor.decorator.js.map +1 -0
- package/dist/core/interceptors/interceptor.interface.d.ts +31 -0
- package/dist/core/interceptors/interceptor.interface.d.ts.map +1 -0
- package/dist/core/interceptors/interceptor.interface.js +2 -0
- package/dist/core/interceptors/interceptor.interface.js.map +1 -0
- package/dist/core/jwt-module.d.ts +51 -0
- package/dist/core/jwt-module.d.ts.map +1 -0
- package/dist/core/jwt-module.js +52 -0
- package/dist/core/jwt-module.js.map +1 -0
- package/dist/core/logger.d.ts +18 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +53 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/middleware/middleware.decorator.d.ts +39 -0
- package/dist/core/middleware/middleware.decorator.d.ts.map +1 -0
- package/dist/core/middleware/middleware.decorator.js +53 -0
- package/dist/core/middleware/middleware.decorator.js.map +1 -0
- package/dist/core/middleware/middleware.interface.d.ts +29 -0
- package/dist/core/middleware/middleware.interface.d.ts.map +1 -0
- package/dist/core/middleware/middleware.interface.js +2 -0
- package/dist/core/middleware/middleware.interface.js.map +1 -0
- package/dist/core/module.d.ts +93 -0
- package/dist/core/module.d.ts.map +1 -0
- package/dist/core/module.js +87 -0
- package/dist/core/module.js.map +1 -0
- package/dist/core/oauth-module.d.ts +123 -0
- package/dist/core/oauth-module.d.ts.map +1 -0
- package/dist/core/oauth-module.js +324 -0
- package/dist/core/oauth-module.js.map +1 -0
- package/dist/core/pipes/pipe.decorator.d.ts +64 -0
- package/dist/core/pipes/pipe.decorator.d.ts.map +1 -0
- package/dist/core/pipes/pipe.decorator.js +85 -0
- package/dist/core/pipes/pipe.decorator.js.map +1 -0
- package/dist/core/pipes/pipe.interface.d.ts +41 -0
- package/dist/core/pipes/pipe.interface.d.ts.map +1 -0
- package/dist/core/pipes/pipe.interface.js +2 -0
- package/dist/core/pipes/pipe.interface.js.map +1 -0
- package/dist/core/prompt.d.ts +46 -0
- package/dist/core/prompt.d.ts.map +1 -0
- package/dist/core/prompt.js +76 -0
- package/dist/core/prompt.js.map +1 -0
- package/dist/core/resource.d.ts +47 -0
- package/dist/core/resource.d.ts.map +1 -0
- package/dist/core/resource.js +90 -0
- package/dist/core/resource.js.map +1 -0
- package/dist/core/server.d.ts +129 -0
- package/dist/core/server.d.ts.map +1 -0
- package/dist/core/server.js +617 -0
- package/dist/core/server.js.map +1 -0
- package/dist/core/tool.d.ts +108 -0
- package/dist/core/tool.d.ts.map +1 -0
- package/dist/core/tool.js +241 -0
- package/dist/core/tool.js.map +1 -0
- package/dist/core/transports/discovery-http-server.d.ts +19 -0
- package/dist/core/transports/discovery-http-server.d.ts.map +1 -0
- package/dist/core/transports/discovery-http-server.js +54 -0
- package/dist/core/transports/discovery-http-server.js.map +1 -0
- package/dist/core/transports/http-server.d.ts +108 -0
- package/dist/core/transports/http-server.d.ts.map +1 -0
- package/dist/core/transports/http-server.js +293 -0
- package/dist/core/transports/http-server.js.map +1 -0
- package/dist/core/transports/streamable-http.d.ts +177 -0
- package/dist/core/transports/streamable-http.d.ts.map +1 -0
- package/dist/core/transports/streamable-http.js +1287 -0
- package/dist/core/transports/streamable-http.js.map +1 -0
- package/dist/core/types.d.ts +195 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/widgets/widget-examples.resource.d.ts +17 -0
- package/dist/core/widgets/widget-examples.resource.d.ts.map +1 -0
- package/dist/core/widgets/widget-examples.resource.js +28 -0
- package/dist/core/widgets/widget-examples.resource.js.map +1 -0
- package/dist/core/widgets/widget-registry.d.ts +56 -0
- package/dist/core/widgets/widget-registry.d.ts.map +1 -0
- package/dist/core/widgets/widget-registry.js +75 -0
- package/dist/core/widgets/widget-registry.js.map +1 -0
- package/dist/testing/index.d.ts +103 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +161 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/ui-next/index.d.ts +31 -0
- package/dist/ui-next/index.d.ts.map +1 -0
- package/dist/ui-next/index.js +687 -0
- package/dist/ui-next/index.js.map +1 -0
- package/package.json +89 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { createProtectedResourceMetadata } from './server-metadata.js';
|
|
2
|
+
import { createAuthMiddleware, requireScopes } from './middleware.js';
|
|
3
|
+
/**
|
|
4
|
+
* Server Integration Utilities
|
|
5
|
+
*
|
|
6
|
+
* Easy integration of OAuth 2.1 auth into MCP servers
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Configure authentication for MCP server
|
|
10
|
+
*
|
|
11
|
+
* This adds:
|
|
12
|
+
* 1. Protected Resource Metadata endpoint
|
|
13
|
+
* 2. Authentication middleware to specified routes
|
|
14
|
+
*
|
|
15
|
+
* @param app - Express application
|
|
16
|
+
* @param config - Auth configuration
|
|
17
|
+
* @param protectRoutes - Routes to protect with auth (default: all /mcp routes)
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const app = express();
|
|
22
|
+
*
|
|
23
|
+
* configureServerAuth(app, {
|
|
24
|
+
* resourceUri: 'https://mcp.example.com',
|
|
25
|
+
* authorizationServers: ['https://auth.example.com'],
|
|
26
|
+
* tokenIntrospectionEndpoint: 'https://auth.example.com/oauth/introspect',
|
|
27
|
+
* tokenIntrospectionClientId: 'mcp-server',
|
|
28
|
+
* tokenIntrospectionClientSecret: process.env.INTROSPECTION_SECRET,
|
|
29
|
+
* audience: 'https://mcp.example.com',
|
|
30
|
+
* scopesSupported: ['mcp:read', 'mcp:write']
|
|
31
|
+
* }, {
|
|
32
|
+
* protectRoutes: ['/mcp/*']
|
|
33
|
+
* });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export function configureServerAuth(app, config, options) {
|
|
37
|
+
const metadataPath = options?.metadataPath || '/.well-known/oauth-protected-resource';
|
|
38
|
+
const protectRoutes = options?.protectRoutes || ['/mcp/*'];
|
|
39
|
+
// 1. Add Protected Resource Metadata endpoint
|
|
40
|
+
app.get(metadataPath, (req, res) => {
|
|
41
|
+
const metadata = createProtectedResourceMetadata(config.resourceUri, config.authorizationServers, config.scopesSupported);
|
|
42
|
+
res.json(metadata);
|
|
43
|
+
});
|
|
44
|
+
// 2. Apply auth middleware to protected routes
|
|
45
|
+
const authMiddleware = createAuthMiddleware(config);
|
|
46
|
+
for (const route of protectRoutes) {
|
|
47
|
+
app.use(route, authMiddleware);
|
|
48
|
+
}
|
|
49
|
+
console.log(`🔐 OAuth 2.1 authentication configured for ${config.resourceUri}`);
|
|
50
|
+
console.log(` Authorization servers: ${config.authorizationServers.join(', ')}`);
|
|
51
|
+
console.log(` Protected routes: ${protectRoutes.join(', ')}`);
|
|
52
|
+
console.log(` Metadata endpoint: ${metadataPath}`);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Scope-based route protection helper
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* const scopes = createScopeGuards(['mcp:read', 'mcp:write', 'mcp:admin']);
|
|
60
|
+
*
|
|
61
|
+
* app.get('/mcp/tools', scopes.read, (req, res) => {
|
|
62
|
+
* // List tools - requires mcp:read
|
|
63
|
+
* });
|
|
64
|
+
*
|
|
65
|
+
* app.post('/mcp/tools/execute', scopes.write, (req, res) => {
|
|
66
|
+
* // Execute tool - requires mcp:write
|
|
67
|
+
* });
|
|
68
|
+
*
|
|
69
|
+
* app.delete('/mcp/resources', scopes.admin, (req, res) => {
|
|
70
|
+
* // Delete resource - requires mcp:admin
|
|
71
|
+
* });
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export function createScopeGuards(scopeConfig) {
|
|
75
|
+
const guards = {};
|
|
76
|
+
for (const [name, scopes] of Object.entries(scopeConfig)) {
|
|
77
|
+
if (scopes && scopes.length > 0) {
|
|
78
|
+
guards[name] = requireScopes(...scopes);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return guards;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Create standard MCP scope configuration
|
|
85
|
+
*
|
|
86
|
+
* Returns scope guards for common MCP operations:
|
|
87
|
+
* - read: List tools, resources, prompts
|
|
88
|
+
* - execute: Execute tools, get prompts
|
|
89
|
+
* - write: Modify resources
|
|
90
|
+
* - admin: Server configuration
|
|
91
|
+
*
|
|
92
|
+
* @param scopePrefix - Scope prefix (default: 'mcp')
|
|
93
|
+
*/
|
|
94
|
+
export function createMCPScopeGuards(scopePrefix = 'mcp') {
|
|
95
|
+
return createScopeGuards({
|
|
96
|
+
read: [`${scopePrefix}:read`],
|
|
97
|
+
execute: [`${scopePrefix}:read`, `${scopePrefix}:execute`],
|
|
98
|
+
write: [`${scopePrefix}:read`, `${scopePrefix}:write`],
|
|
99
|
+
admin: [`${scopePrefix}:admin`],
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Generate suggested scopes for MCP server
|
|
104
|
+
*
|
|
105
|
+
* Returns standard scope definitions for MCP operations
|
|
106
|
+
*/
|
|
107
|
+
export function getStandardMCPScopes(scopePrefix = 'mcp') {
|
|
108
|
+
const scopes = [
|
|
109
|
+
`${scopePrefix}:read`,
|
|
110
|
+
`${scopePrefix}:execute`,
|
|
111
|
+
`${scopePrefix}:write`,
|
|
112
|
+
`${scopePrefix}:admin`,
|
|
113
|
+
];
|
|
114
|
+
const descriptions = {
|
|
115
|
+
[`${scopePrefix}:read`]: 'Read access to tools, resources, and prompts',
|
|
116
|
+
[`${scopePrefix}:execute`]: 'Execute tools and get prompts',
|
|
117
|
+
[`${scopePrefix}:write`]: 'Modify resources and server state',
|
|
118
|
+
[`${scopePrefix}:admin`]: 'Administrative access to server configuration',
|
|
119
|
+
};
|
|
120
|
+
return { scopes, descriptions };
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Helper to validate auth configuration
|
|
124
|
+
*/
|
|
125
|
+
export function validateAuthConfig(config) {
|
|
126
|
+
const errors = [];
|
|
127
|
+
const warnings = [];
|
|
128
|
+
// Required fields
|
|
129
|
+
if (!config.resourceUri) {
|
|
130
|
+
errors.push('resourceUri is required');
|
|
131
|
+
}
|
|
132
|
+
if (!config.authorizationServers || config.authorizationServers.length === 0) {
|
|
133
|
+
errors.push('At least one authorization server is required');
|
|
134
|
+
}
|
|
135
|
+
// Token validation method
|
|
136
|
+
const hasIntrospection = !!config.tokenIntrospectionEndpoint;
|
|
137
|
+
const hasJWT = !!config.jwksUri;
|
|
138
|
+
if (!hasIntrospection && !hasJWT) {
|
|
139
|
+
errors.push('Either tokenIntrospectionEndpoint or jwksUri must be configured');
|
|
140
|
+
}
|
|
141
|
+
// Introspection credentials
|
|
142
|
+
if (hasIntrospection) {
|
|
143
|
+
if (!config.tokenIntrospectionClientId) {
|
|
144
|
+
warnings.push('tokenIntrospectionClientId not set - introspection may fail');
|
|
145
|
+
}
|
|
146
|
+
if (!config.tokenIntrospectionClientSecret) {
|
|
147
|
+
warnings.push('tokenIntrospectionClientSecret not set - introspection may fail');
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// JWT validation
|
|
151
|
+
if (hasJWT) {
|
|
152
|
+
if (!config.audience) {
|
|
153
|
+
errors.push('audience is required for JWT validation (prevents confused deputy attacks)');
|
|
154
|
+
}
|
|
155
|
+
if (!config.issuer) {
|
|
156
|
+
warnings.push('issuer not set - JWT validation may be less strict');
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// Audience (critical for security)
|
|
160
|
+
if (!config.audience) {
|
|
161
|
+
warnings.push('audience not set - tokens will not be validated for this resource. ' +
|
|
162
|
+
'This is a security risk (confused deputy attacks).');
|
|
163
|
+
}
|
|
164
|
+
// HTTPS
|
|
165
|
+
if (config.requireHttps !== false && process.env.NODE_ENV === 'production') {
|
|
166
|
+
try {
|
|
167
|
+
const url = new URL(config.resourceUri);
|
|
168
|
+
if (url.protocol !== 'https:') {
|
|
169
|
+
errors.push('resourceUri must use HTTPS in production');
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
errors.push('resourceUri is not a valid URL');
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
valid: errors.length === 0,
|
|
178
|
+
errors,
|
|
179
|
+
warnings,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=server-integration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-integration.js","sourceRoot":"","sources":["../../src/auth/server-integration.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { ProtectedResourceMetadata } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Protected Resource Metadata (RFC 9728)
|
|
4
|
+
*
|
|
5
|
+
* MCP servers MUST implement this to advertise their authorization servers
|
|
6
|
+
* to MCP clients. This enables automatic discovery of auth configuration.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Create protected resource metadata document
|
|
10
|
+
*
|
|
11
|
+
* @param resourceUri - The URI of this MCP server
|
|
12
|
+
* @param authorizationServers - Array of authorization server issuer URLs
|
|
13
|
+
* @param scopesSupported - Optional: scopes this resource supports
|
|
14
|
+
*/
|
|
15
|
+
export declare function createProtectedResourceMetadata(resourceUri: string, authorizationServers: string[], scopesSupported?: string[]): ProtectedResourceMetadata;
|
|
16
|
+
/**
|
|
17
|
+
* Get well-known URI for protected resource metadata
|
|
18
|
+
* Per RFC 9728, can be at:
|
|
19
|
+
* 1. Resource path: /.well-known/oauth-protected-resource{path}
|
|
20
|
+
* 2. Root: /.well-known/oauth-protected-resource
|
|
21
|
+
*/
|
|
22
|
+
export declare function getWellKnownMetadataUris(resourceUrl: URL): string[];
|
|
23
|
+
/**
|
|
24
|
+
* Generate WWW-Authenticate header value for 401 responses
|
|
25
|
+
* Per RFC 6750 and MCP spec
|
|
26
|
+
*
|
|
27
|
+
* @param resourceMetadataUrl - URL to protected resource metadata
|
|
28
|
+
* @param scope - Optional: required scopes for this request
|
|
29
|
+
* @param error - Optional: error code (invalid_token, insufficient_scope, etc.)
|
|
30
|
+
* @param errorDescription - Optional: human-readable error description
|
|
31
|
+
*/
|
|
32
|
+
export declare function generateWWWAuthenticateHeader(options: {
|
|
33
|
+
resourceMetadataUrl?: string;
|
|
34
|
+
scope?: string;
|
|
35
|
+
error?: string;
|
|
36
|
+
errorDescription?: string;
|
|
37
|
+
realm?: string;
|
|
38
|
+
}): string;
|
|
39
|
+
/**
|
|
40
|
+
* Parse WWW-Authenticate header
|
|
41
|
+
* Extracts Bearer auth challenge parameters
|
|
42
|
+
*/
|
|
43
|
+
export declare function parseWWWAuthenticateHeader(headerValue: string): {
|
|
44
|
+
scheme: string;
|
|
45
|
+
realm?: string;
|
|
46
|
+
scope?: string;
|
|
47
|
+
resourceMetadata?: string;
|
|
48
|
+
error?: string;
|
|
49
|
+
errorDescription?: string;
|
|
50
|
+
} | null;
|
|
51
|
+
//# sourceMappingURL=server-metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-metadata.d.ts","sourceRoot":"","sources":["../../src/auth/server-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAEvD;;;;;GAKG;AAEH;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAC7C,WAAW,EAAE,MAAM,EACnB,oBAAoB,EAAE,MAAM,EAAE,EAC9B,eAAe,CAAC,EAAE,MAAM,EAAE,GACzB,yBAAyB,CAO3B;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,GAAG,GAAG,MAAM,EAAE,CAcnE;AAED;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE;IACrD,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,MAAM,CAwBT;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,GAAG;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,GAAG,IAAI,CA2CP"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Protected Resource Metadata (RFC 9728)
|
|
3
|
+
*
|
|
4
|
+
* MCP servers MUST implement this to advertise their authorization servers
|
|
5
|
+
* to MCP clients. This enables automatic discovery of auth configuration.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Create protected resource metadata document
|
|
9
|
+
*
|
|
10
|
+
* @param resourceUri - The URI of this MCP server
|
|
11
|
+
* @param authorizationServers - Array of authorization server issuer URLs
|
|
12
|
+
* @param scopesSupported - Optional: scopes this resource supports
|
|
13
|
+
*/
|
|
14
|
+
export function createProtectedResourceMetadata(resourceUri, authorizationServers, scopesSupported) {
|
|
15
|
+
return {
|
|
16
|
+
resource: resourceUri,
|
|
17
|
+
authorization_servers: authorizationServers,
|
|
18
|
+
scopes_supported: scopesSupported,
|
|
19
|
+
bearer_methods_supported: ['header'], // MCP uses Bearer tokens in headers
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get well-known URI for protected resource metadata
|
|
24
|
+
* Per RFC 9728, can be at:
|
|
25
|
+
* 1. Resource path: /.well-known/oauth-protected-resource{path}
|
|
26
|
+
* 2. Root: /.well-known/oauth-protected-resource
|
|
27
|
+
*/
|
|
28
|
+
export function getWellKnownMetadataUris(resourceUrl) {
|
|
29
|
+
const urls = [];
|
|
30
|
+
// Method 1: At the path of the resource
|
|
31
|
+
if (resourceUrl.pathname && resourceUrl.pathname !== '/') {
|
|
32
|
+
const pathUri = new URL('/.well-known/oauth-protected-resource' + resourceUrl.pathname, resourceUrl.origin);
|
|
33
|
+
urls.push(pathUri.toString());
|
|
34
|
+
}
|
|
35
|
+
// Method 2: At the root
|
|
36
|
+
const rootUri = new URL('/.well-known/oauth-protected-resource', resourceUrl.origin);
|
|
37
|
+
urls.push(rootUri.toString());
|
|
38
|
+
return urls;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Generate WWW-Authenticate header value for 401 responses
|
|
42
|
+
* Per RFC 6750 and MCP spec
|
|
43
|
+
*
|
|
44
|
+
* @param resourceMetadataUrl - URL to protected resource metadata
|
|
45
|
+
* @param scope - Optional: required scopes for this request
|
|
46
|
+
* @param error - Optional: error code (invalid_token, insufficient_scope, etc.)
|
|
47
|
+
* @param errorDescription - Optional: human-readable error description
|
|
48
|
+
*/
|
|
49
|
+
export function generateWWWAuthenticateHeader(options) {
|
|
50
|
+
const parts = ['Bearer'];
|
|
51
|
+
if (options.realm) {
|
|
52
|
+
parts.push(`realm="${options.realm}"`);
|
|
53
|
+
}
|
|
54
|
+
if (options.scope) {
|
|
55
|
+
parts.push(`scope="${options.scope}"`);
|
|
56
|
+
}
|
|
57
|
+
if (options.resourceMetadataUrl) {
|
|
58
|
+
parts.push(`resource_metadata="${options.resourceMetadataUrl}"`);
|
|
59
|
+
}
|
|
60
|
+
if (options.error) {
|
|
61
|
+
parts.push(`error="${options.error}"`);
|
|
62
|
+
}
|
|
63
|
+
if (options.errorDescription) {
|
|
64
|
+
parts.push(`error_description="${options.errorDescription}"`);
|
|
65
|
+
}
|
|
66
|
+
return parts.join(', ');
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Parse WWW-Authenticate header
|
|
70
|
+
* Extracts Bearer auth challenge parameters
|
|
71
|
+
*/
|
|
72
|
+
export function parseWWWAuthenticateHeader(headerValue) {
|
|
73
|
+
if (!headerValue)
|
|
74
|
+
return null;
|
|
75
|
+
// Parse Bearer scheme
|
|
76
|
+
const bearerMatch = headerValue.match(/Bearer\s+(.+)/i);
|
|
77
|
+
if (!bearerMatch)
|
|
78
|
+
return null;
|
|
79
|
+
const params = bearerMatch[1];
|
|
80
|
+
const result = { scheme: 'Bearer' };
|
|
81
|
+
// Parse key="value" pairs
|
|
82
|
+
const paramRegex = /(\w+)="([^"]+)"/g;
|
|
83
|
+
let match;
|
|
84
|
+
while ((match = paramRegex.exec(params)) !== null) {
|
|
85
|
+
const [, key, value] = match;
|
|
86
|
+
switch (key) {
|
|
87
|
+
case 'realm':
|
|
88
|
+
result.realm = value;
|
|
89
|
+
break;
|
|
90
|
+
case 'scope':
|
|
91
|
+
result.scope = value;
|
|
92
|
+
break;
|
|
93
|
+
case 'resource_metadata':
|
|
94
|
+
result.resourceMetadata = value;
|
|
95
|
+
break;
|
|
96
|
+
case 'error':
|
|
97
|
+
result.error = value;
|
|
98
|
+
break;
|
|
99
|
+
case 'error_description':
|
|
100
|
+
result.errorDescription = value;
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=server-metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-metadata.js","sourceRoot":"","sources":["../../src/auth/server-metadata.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { RequestHandler } from 'express';
|
|
2
|
+
import { SecretValue } from './secure-secret.js';
|
|
3
|
+
/**
|
|
4
|
+
* Simple JWT Authentication
|
|
5
|
+
*
|
|
6
|
+
* For 70% of use cases where you don't need full OAuth 2.1 complexity.
|
|
7
|
+
* Perfect for internal tools, APIs, and services that manage their own tokens.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Standard JWT claims that are commonly used
|
|
11
|
+
*/
|
|
12
|
+
export interface StandardJWTClaims {
|
|
13
|
+
/** Subject - typically user ID */
|
|
14
|
+
sub?: string;
|
|
15
|
+
/** Audience - who the token is intended for */
|
|
16
|
+
aud?: string | string[];
|
|
17
|
+
/** Issuer - who created the token */
|
|
18
|
+
iss?: string;
|
|
19
|
+
/** Expiration time (unix timestamp) */
|
|
20
|
+
exp?: number;
|
|
21
|
+
/** Issued at (unix timestamp) */
|
|
22
|
+
iat?: number;
|
|
23
|
+
/** Not before (unix timestamp) */
|
|
24
|
+
nbf?: number;
|
|
25
|
+
/** JWT ID - unique identifier */
|
|
26
|
+
jti?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Custom claims that can be added to JWT payload
|
|
30
|
+
*/
|
|
31
|
+
export interface CustomJWTClaims {
|
|
32
|
+
/** User scopes/permissions */
|
|
33
|
+
scopes?: string[];
|
|
34
|
+
/** Space-separated scopes (OAuth style) */
|
|
35
|
+
scope?: string;
|
|
36
|
+
/** Client ID for machine-to-machine auth */
|
|
37
|
+
client_id?: string;
|
|
38
|
+
/** User's email */
|
|
39
|
+
email?: string;
|
|
40
|
+
/** User's name */
|
|
41
|
+
name?: string;
|
|
42
|
+
/** User roles */
|
|
43
|
+
roles?: string[];
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Full JWT payload combining standard and custom claims
|
|
47
|
+
*/
|
|
48
|
+
export interface JWTPayload extends StandardJWTClaims, CustomJWTClaims {
|
|
49
|
+
/** Allow additional custom claims */
|
|
50
|
+
[key: string]: unknown;
|
|
51
|
+
}
|
|
52
|
+
export interface SimpleJWTConfig {
|
|
53
|
+
/**
|
|
54
|
+
* JWT secret for signing/verification (HS256)
|
|
55
|
+
*
|
|
56
|
+
* **Recommended:** Use SecretValue.fromEnv() to load from environment
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* // Recommended: Load from environment
|
|
61
|
+
* import { SecretValue } from '@nitrostack/sdk/auth';
|
|
62
|
+
*
|
|
63
|
+
* const config = {
|
|
64
|
+
* secret: SecretValue.fromEnv('JWT_SECRET'),
|
|
65
|
+
* audience: 'my-api',
|
|
66
|
+
* };
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
secret: SecretValue | string;
|
|
70
|
+
/**
|
|
71
|
+
* Expected audience (who the token is for)
|
|
72
|
+
*/
|
|
73
|
+
audience?: string;
|
|
74
|
+
/**
|
|
75
|
+
* Expected issuer (who created the token)
|
|
76
|
+
*/
|
|
77
|
+
issuer?: string;
|
|
78
|
+
/**
|
|
79
|
+
* Custom claims to validate
|
|
80
|
+
*/
|
|
81
|
+
customValidation?: (payload: JWTPayload) => boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Algorithm (default: HS256)
|
|
84
|
+
*/
|
|
85
|
+
algorithm?: 'HS256' | 'HS384' | 'HS512';
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Create Simple JWT authentication middleware
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```typescript
|
|
92
|
+
* const server = createServer({...});
|
|
93
|
+
*
|
|
94
|
+
* // Simple JWT auth (no OAuth complexity!)
|
|
95
|
+
* server.app.use('/mcp', createSimpleJWTAuth({
|
|
96
|
+
* secret: process.env.JWT_SECRET!,
|
|
97
|
+
* audience: 'my-mcp-server',
|
|
98
|
+
* issuer: 'my-app',
|
|
99
|
+
* }));
|
|
100
|
+
*
|
|
101
|
+
* server.start();
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
export declare function createSimpleJWTAuth(config: SimpleJWTConfig): RequestHandler;
|
|
105
|
+
/**
|
|
106
|
+
* Generate a JWT token (helper for testing/development)
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```typescript
|
|
110
|
+
* const token = generateJWT({
|
|
111
|
+
* secret: process.env.JWT_SECRET!,
|
|
112
|
+
* payload: {
|
|
113
|
+
* sub: 'user123',
|
|
114
|
+
* scopes: ['mcp:read', 'mcp:write'],
|
|
115
|
+
* },
|
|
116
|
+
* expiresIn: '1h',
|
|
117
|
+
* });
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
/**
|
|
121
|
+
* Options for generating a JWT token
|
|
122
|
+
*/
|
|
123
|
+
export interface GenerateJWTOptions {
|
|
124
|
+
/**
|
|
125
|
+
* JWT secret for signing
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```typescript
|
|
129
|
+
* secret: SecretValue.fromEnv('JWT_SECRET')
|
|
130
|
+
* // or for testing:
|
|
131
|
+
* secret: SecretValue.fromValue('test-secret', { allowHardcoded: true })
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
secret: SecretValue | string;
|
|
135
|
+
/** Payload to encode in the JWT */
|
|
136
|
+
payload: JWTPayload;
|
|
137
|
+
/** Token expiration (e.g., '1h', '7d', 3600) */
|
|
138
|
+
expiresIn?: string | number;
|
|
139
|
+
/** Expected audience */
|
|
140
|
+
audience?: string;
|
|
141
|
+
/** Token issuer */
|
|
142
|
+
issuer?: string;
|
|
143
|
+
/** Signing algorithm */
|
|
144
|
+
algorithm?: 'HS256' | 'HS384' | 'HS512';
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Generate a JWT token
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* ```typescript
|
|
151
|
+
* const token = generateJWT({
|
|
152
|
+
* secret: SecretValue.fromEnv('JWT_SECRET'),
|
|
153
|
+
* payload: {
|
|
154
|
+
* sub: 'user123',
|
|
155
|
+
* scopes: ['mcp:read', 'mcp:write'],
|
|
156
|
+
* },
|
|
157
|
+
* expiresIn: '1h',
|
|
158
|
+
* });
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
161
|
+
export declare function generateJWT(options: GenerateJWTOptions): string;
|
|
162
|
+
/**
|
|
163
|
+
* Verify a JWT token without middleware (helper)
|
|
164
|
+
*
|
|
165
|
+
* @param token - The JWT token to verify
|
|
166
|
+
* @param config - JWT configuration including secret
|
|
167
|
+
* @returns The decoded payload if valid, null otherwise
|
|
168
|
+
*/
|
|
169
|
+
export declare function verifyJWT(token: string, config: SimpleJWTConfig): JWTPayload | null;
|
|
170
|
+
/**
|
|
171
|
+
* Decode JWT without verification (for debugging)
|
|
172
|
+
*/
|
|
173
|
+
export declare function decodeJWT(token: string): JWTPayload | null;
|
|
174
|
+
//# sourceMappingURL=simple-jwt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simple-jwt.d.ts","sourceRoot":"","sources":["../../src/auth/simple-jwt.ts"],"names":[],"mappings":"AACA,OAAO,EAAmC,cAAc,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAgB,MAAM,oBAAoB,CAAC;AAE/D;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,kCAAkC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,qCAAqC;IACrC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,8BAA8B;IAC9B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,2CAA2C;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mBAAmB;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kBAAkB;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iBAAiB;IACjB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,UAAW,SAAQ,iBAAiB,EAAE,eAAe;IACpE,qCAAqC;IACrC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B;;;;;;;;;;;;;;;OAeG;IACH,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC;IAE7B;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,OAAO,CAAC;IAEpD;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;CACzC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,eAAe,GAAG,cAAc,CAiF3E;AAED;;;;;;;;;;;;;;GAcG;AACH;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;;;;;;OASG;IACH,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC;IAE7B,mCAAmC;IACnC,OAAO,EAAE,UAAU,CAAC;IAEpB,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAE5B,wBAAwB;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,mBAAmB;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,wBAAwB;IACxB,SAAS,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;CACzC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,CAoB/D;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,eAAe,GACtB,UAAU,GAAG,IAAI,CAyBnB;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAM1D"}
|