nitrostack 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/CHANGELOG.md +227 -0
- package/CONTRIBUTING.md +182 -0
- package/LICENSE +201 -0
- package/LICENSE_URLS_UPDATE_COMPLETE.md +388 -0
- package/NOTICE +153 -0
- package/README.md +571 -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 +30 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +43 -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/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 +88 -0
- package/dist/auth/simple-jwt.d.ts.map +1 -0
- package/dist/auth/simple-jwt.js +152 -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 +47 -0
- package/dist/auth/token-validation.d.ts.map +1 -0
- package/dist/auth/token-validation.js +237 -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/cli/commands/build.d.ts +6 -0
- package/dist/cli/commands/build.d.ts.map +1 -0
- package/dist/cli/commands/build.js +104 -0
- package/dist/cli/commands/build.js.map +1 -0
- package/dist/cli/commands/dev.d.ts +7 -0
- package/dist/cli/commands/dev.d.ts.map +1 -0
- package/dist/cli/commands/dev.js +312 -0
- package/dist/cli/commands/dev.js.map +1 -0
- package/dist/cli/commands/generate-types.d.ts +8 -0
- package/dist/cli/commands/generate-types.d.ts.map +1 -0
- package/dist/cli/commands/generate-types.js +220 -0
- package/dist/cli/commands/generate-types.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +5 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +365 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/commands/init.d.ts +7 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +365 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/start.d.ts +6 -0
- package/dist/cli/commands/start.d.ts.map +1 -0
- package/dist/cli/commands/start.js +61 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +47 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/mcp-dev-wrapper.d.ts +3 -0
- package/dist/cli/mcp-dev-wrapper.d.ts.map +1 -0
- package/dist/cli/mcp-dev-wrapper.js +116 -0
- package/dist/cli/mcp-dev-wrapper.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 +58 -0
- package/dist/core/app-decorator.d.ts.map +1 -0
- package/dist/core/app-decorator.js +261 -0
- package/dist/core/app-decorator.js.map +1 -0
- package/dist/core/builders.d.ts +38 -0
- package/dist/core/builders.d.ts.map +1 -0
- package/dist/core/builders.js +129 -0
- package/dist/core/builders.js.map +1 -0
- package/dist/core/component.d.ts +105 -0
- package/dist/core/component.d.ts.map +1 -0
- package/dist/core/component.js +182 -0
- package/dist/core/component.js.map +1 -0
- package/dist/core/config-module.d.ts +55 -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 +62 -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 +151 -0
- package/dist/core/decorators.d.ts.map +1 -0
- package/dist/core/decorators.js +142 -0
- package/dist/core/decorators.js.map +1 -0
- package/dist/core/di/container.d.ts +42 -0
- package/dist/core/di/container.d.ts.map +1 -0
- package/dist/core/di/container.js +76 -0
- package/dist/core/di/container.js.map +1 -0
- package/dist/core/di/injectable.decorator.d.ts +35 -0
- package/dist/core/di/injectable.decorator.d.ts.map +1 -0
- package/dist/core/di/injectable.decorator.js +57 -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 +68 -0
- package/dist/core/events/event.decorator.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 +30 -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 +55 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +57 -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 +51 -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 +74 -0
- package/dist/core/module.d.ts.map +1 -0
- package/dist/core/module.js +82 -0
- package/dist/core/module.js.map +1 -0
- package/dist/core/oauth-module.d.ts +144 -0
- package/dist/core/oauth-module.d.ts.map +1 -0
- package/dist/core/oauth-module.js +190 -0
- package/dist/core/oauth-module.js.map +1 -0
- package/dist/core/pipes/pipe.decorator.d.ts +55 -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 +36 -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 +37 -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 +42 -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 +72 -0
- package/dist/core/server.d.ts.map +1 -0
- package/dist/core/server.js +406 -0
- package/dist/core/server.js.map +1 -0
- package/dist/core/tool.d.ts +78 -0
- package/dist/core/tool.d.ts.map +1 -0
- package/dist/core/tool.js +190 -0
- package/dist/core/tool.js.map +1 -0
- package/dist/core/transports/http-server.d.ts +102 -0
- package/dist/core/transports/http-server.d.ts.map +1 -0
- package/dist/core/transports/http-server.js +265 -0
- package/dist/core/transports/http-server.js.map +1 -0
- package/dist/core/types.d.ts +123 -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 +82 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +164 -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/dist/widgets/index.d.ts +9 -0
- package/dist/widgets/index.d.ts.map +1 -0
- package/dist/widgets/index.js +9 -0
- package/dist/widgets/index.js.map +1 -0
- package/dist/widgets/metadata.d.ts +53 -0
- package/dist/widgets/metadata.d.ts.map +1 -0
- package/dist/widgets/metadata.js +29 -0
- package/dist/widgets/metadata.js.map +1 -0
- package/dist/widgets/withToolData.d.ts +19 -0
- package/dist/widgets/withToolData.d.ts.map +1 -0
- package/dist/widgets/withToolData.js +240 -0
- package/dist/widgets/withToolData.js.map +1 -0
- package/jest.config.js +21 -0
- package/package.json +108 -0
- package/templates/typescript-auth/AI_AGENT_CLI_REFERENCE.md +702 -0
- package/templates/typescript-auth/AI_AGENT_SDK_REFERENCE.md +1260 -0
- package/templates/typescript-auth/README.md +400 -0
- package/templates/typescript-auth/package.json +44 -0
- package/templates/typescript-auth-api-key/AI_AGENT_CLI_REFERENCE.md +701 -0
- package/templates/typescript-auth-api-key/AI_AGENT_SDK_REFERENCE.md +1260 -0
- package/templates/typescript-auth-api-key/README.md +483 -0
- package/templates/typescript-auth-api-key/package-lock.json +124 -0
- package/templates/typescript-auth-api-key/package.json +29 -0
- package/templates/typescript-oauth/AI_AGENT_CLI_REFERENCE.md +701 -0
- package/templates/typescript-oauth/AI_AGENT_SDK_REFERENCE.md +1260 -0
- package/templates/typescript-oauth/OAUTH_SETUP.md +406 -0
- package/templates/typescript-oauth/README.md +350 -0
- package/templates/typescript-oauth/package.json +30 -0
- package/templates/typescript-starter/AI_AGENT_CLI_REFERENCE.md +701 -0
- package/templates/typescript-starter/AI_AGENT_SDK_REFERENCE.md +1260 -0
- package/templates/typescript-starter/README.md +312 -0
- package/templates/typescript-starter/package.json +32 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
2
|
+
/**
|
|
3
|
+
* Create API Key authentication middleware
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* const server = createServer({...});
|
|
8
|
+
*
|
|
9
|
+
* // Simple API key auth
|
|
10
|
+
* server.app.use('/mcp', createAPIKeyAuth({
|
|
11
|
+
* keys: [
|
|
12
|
+
* process.env.API_KEY_1!,
|
|
13
|
+
* process.env.API_KEY_2!,
|
|
14
|
+
* ],
|
|
15
|
+
* headerName: 'X-API-Key',
|
|
16
|
+
* }));
|
|
17
|
+
*
|
|
18
|
+
* server.start();
|
|
19
|
+
*
|
|
20
|
+
* // Client usage:
|
|
21
|
+
* // curl -H "X-API-Key: your-api-key" https://mcp.example.com/mcp/tools
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export function createAPIKeyAuth(config) {
|
|
25
|
+
const headerName = config.headerName || 'x-api-key';
|
|
26
|
+
const queryParamName = config.queryParamName || 'api_key';
|
|
27
|
+
// Validate config
|
|
28
|
+
if (!config.keys || config.keys.length === 0) {
|
|
29
|
+
throw new Error('API key auth requires at least one key');
|
|
30
|
+
}
|
|
31
|
+
return async (req, res, next) => {
|
|
32
|
+
try {
|
|
33
|
+
// 1. Extract API key from header or query
|
|
34
|
+
let apiKey;
|
|
35
|
+
// Try header first (recommended)
|
|
36
|
+
apiKey = req.headers[headerName.toLowerCase()];
|
|
37
|
+
// Try query parameter (if allowed)
|
|
38
|
+
if (!apiKey && config.allowQueryParam) {
|
|
39
|
+
apiKey = req.query[queryParamName];
|
|
40
|
+
}
|
|
41
|
+
if (!apiKey) {
|
|
42
|
+
return res.status(401).json({
|
|
43
|
+
error: 'unauthorized',
|
|
44
|
+
message: `Missing API key. Provide in ${headerName} header${config.allowQueryParam ? ` or ${queryParamName} query parameter` : ''}`,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
// 2. Validate API key
|
|
48
|
+
let isValid = false;
|
|
49
|
+
if (config.hashed) {
|
|
50
|
+
// Compare hashed values
|
|
51
|
+
const hashedKey = hashAPIKey(apiKey);
|
|
52
|
+
isValid = config.keys.includes(hashedKey);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
// Direct comparison
|
|
56
|
+
isValid = config.keys.includes(apiKey);
|
|
57
|
+
}
|
|
58
|
+
// 3. Custom validation
|
|
59
|
+
if (config.customValidation) {
|
|
60
|
+
const customValid = await config.customValidation(apiKey);
|
|
61
|
+
isValid = isValid && customValid;
|
|
62
|
+
}
|
|
63
|
+
if (!isValid) {
|
|
64
|
+
return res.status(401).json({
|
|
65
|
+
error: 'unauthorized',
|
|
66
|
+
message: 'Invalid API key',
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
// 4. Attach to request
|
|
70
|
+
req.auth = {
|
|
71
|
+
authenticated: true,
|
|
72
|
+
tokenInfo: {
|
|
73
|
+
active: true,
|
|
74
|
+
},
|
|
75
|
+
scopes: ['*'], // API keys typically have full access
|
|
76
|
+
clientId: `apikey_${hashAPIKey(apiKey).substring(0, 8)}`,
|
|
77
|
+
subject: undefined,
|
|
78
|
+
};
|
|
79
|
+
next();
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
return res.status(500).json({
|
|
83
|
+
error: 'server_error',
|
|
84
|
+
message: 'API key validation failed',
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Generate a secure API key
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```typescript
|
|
94
|
+
* const apiKey = generateAPIKey();
|
|
95
|
+
* console.log('API Key:', apiKey);
|
|
96
|
+
* // Save to .env: API_KEY_1=sk_...
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export function generateAPIKey(prefix = 'sk') {
|
|
100
|
+
const randomBytes = crypto.randomBytes(32);
|
|
101
|
+
const key = randomBytes.toString('base64url');
|
|
102
|
+
return `${prefix}_${key}`;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Hash an API key (SHA-256)
|
|
106
|
+
* Use this to store hashed keys instead of plain text
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```typescript
|
|
110
|
+
* const apiKey = 'sk_abc123...';
|
|
111
|
+
* const hashed = hashAPIKey(apiKey);
|
|
112
|
+
* // Store hashed in database
|
|
113
|
+
*
|
|
114
|
+
* // In config:
|
|
115
|
+
* createAPIKeyAuth({
|
|
116
|
+
* keys: [hashed],
|
|
117
|
+
* hashed: true,
|
|
118
|
+
* });
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
export function hashAPIKey(key) {
|
|
122
|
+
return crypto.createHash('sha256').update(key).digest('hex');
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Validate API key format
|
|
126
|
+
*/
|
|
127
|
+
export function isValidAPIKeyFormat(key, prefix) {
|
|
128
|
+
if (prefix) {
|
|
129
|
+
return key.startsWith(`${prefix}_`) && key.length > prefix.length + 10;
|
|
130
|
+
}
|
|
131
|
+
return key.length >= 32;
|
|
132
|
+
}
|
|
133
|
+
export function generateAPIKeyWithMetadata(options) {
|
|
134
|
+
const key = generateAPIKey(options.prefix);
|
|
135
|
+
const hashed = hashAPIKey(key);
|
|
136
|
+
const createdAt = new Date();
|
|
137
|
+
let expiresAt;
|
|
138
|
+
if (options.expiresIn) {
|
|
139
|
+
expiresAt = new Date();
|
|
140
|
+
expiresAt.setDate(expiresAt.getDate() + options.expiresIn);
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
key,
|
|
144
|
+
hashed,
|
|
145
|
+
name: options.name,
|
|
146
|
+
createdAt,
|
|
147
|
+
expiresAt,
|
|
148
|
+
scopes: options.scopes,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Validate API key with metadata (expiration, scopes)
|
|
153
|
+
*/
|
|
154
|
+
export function validateAPIKeyWithMetadata(key, metadata, requiredScopes) {
|
|
155
|
+
// Check expiration
|
|
156
|
+
if (metadata.expiresAt && new Date() > metadata.expiresAt) {
|
|
157
|
+
return { valid: false, reason: 'API key has expired' };
|
|
158
|
+
}
|
|
159
|
+
// Check scopes
|
|
160
|
+
if (requiredScopes && metadata.scopes) {
|
|
161
|
+
const hasAllScopes = requiredScopes.every(scope => metadata.scopes.includes(scope) || metadata.scopes.includes('*'));
|
|
162
|
+
if (!hasAllScopes) {
|
|
163
|
+
return { valid: false, reason: 'API key does not have required scopes' };
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return { valid: true };
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=api-key.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-key.js","sourceRoot":"","sources":["../../src/auth/api-key.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { ProtectedResourceMetadata, AuthorizationServerMetadata, ClientRegistrationRequest, ClientRegistrationResponse, TokenResponse, McpAuthClientConfig } from './types.js';
|
|
2
|
+
import { PKCEParams } from './pkce.js';
|
|
3
|
+
/**
|
|
4
|
+
* OAuth 2.1 Client for MCP
|
|
5
|
+
*
|
|
6
|
+
* Handles:
|
|
7
|
+
* - Protected Resource Metadata discovery (RFC 9728)
|
|
8
|
+
* - Authorization Server Metadata discovery (RFC 8414)
|
|
9
|
+
* - Dynamic Client Registration (RFC 7591)
|
|
10
|
+
* - Authorization Code Flow with PKCE (OAuth 2.1)
|
|
11
|
+
* - Token refresh and revocation
|
|
12
|
+
*/
|
|
13
|
+
export declare class OAuth2Client {
|
|
14
|
+
private config;
|
|
15
|
+
constructor(config: McpAuthClientConfig);
|
|
16
|
+
/**
|
|
17
|
+
* Discover Protected Resource Metadata (RFC 9728)
|
|
18
|
+
*
|
|
19
|
+
* Tries:
|
|
20
|
+
* 1. WWW-Authenticate header from 401 response
|
|
21
|
+
* 2. Well-known URI at resource path
|
|
22
|
+
* 3. Well-known URI at root
|
|
23
|
+
*
|
|
24
|
+
* @param resourceUrl - URL of the MCP server
|
|
25
|
+
*/
|
|
26
|
+
discoverProtectedResourceMetadata(resourceUrl: string): Promise<ProtectedResourceMetadata>;
|
|
27
|
+
/**
|
|
28
|
+
* Discover Authorization Server Metadata (RFC 8414)
|
|
29
|
+
*
|
|
30
|
+
* Supports both:
|
|
31
|
+
* - OAuth 2.0 Authorization Server Metadata (RFC 8414)
|
|
32
|
+
* - OpenID Connect Discovery 1.0
|
|
33
|
+
*
|
|
34
|
+
* @param issuer - Authorization server issuer URL
|
|
35
|
+
*/
|
|
36
|
+
discoverAuthorizationServerMetadata(issuer: string): Promise<AuthorizationServerMetadata>;
|
|
37
|
+
/**
|
|
38
|
+
* Register client dynamically (RFC 7591)
|
|
39
|
+
*
|
|
40
|
+
* @param registrationEndpoint - Client registration endpoint
|
|
41
|
+
* @param metadata - Client metadata
|
|
42
|
+
*/
|
|
43
|
+
registerClient(registrationEndpoint: string, metadata: ClientRegistrationRequest): Promise<ClientRegistrationResponse>;
|
|
44
|
+
/**
|
|
45
|
+
* Start authorization flow
|
|
46
|
+
*
|
|
47
|
+
* Generates authorization URL with PKCE parameters
|
|
48
|
+
*
|
|
49
|
+
* @param authzEndpoint - Authorization endpoint
|
|
50
|
+
* @param clientId - OAuth client ID
|
|
51
|
+
* @param redirectUri - Redirect URI
|
|
52
|
+
* @param scope - Requested scopes
|
|
53
|
+
* @param resource - Resource indicator (RFC 8707)
|
|
54
|
+
* @returns Authorization URL and PKCE parameters (store for token exchange)
|
|
55
|
+
*/
|
|
56
|
+
startAuthorizationFlow(options: {
|
|
57
|
+
authorizationEndpoint: string;
|
|
58
|
+
clientId: string;
|
|
59
|
+
redirectUri: string;
|
|
60
|
+
scope?: string;
|
|
61
|
+
resource?: string;
|
|
62
|
+
state?: string;
|
|
63
|
+
}): Promise<{
|
|
64
|
+
authUrl: string;
|
|
65
|
+
state: string;
|
|
66
|
+
pkce: PKCEParams;
|
|
67
|
+
}>;
|
|
68
|
+
/**
|
|
69
|
+
* Exchange authorization code for access token
|
|
70
|
+
*
|
|
71
|
+
* @param code - Authorization code from callback
|
|
72
|
+
* @param pkce - PKCE parameters from startAuthorizationFlow
|
|
73
|
+
* @param tokenEndpoint - Token endpoint
|
|
74
|
+
* @param clientId - OAuth client ID
|
|
75
|
+
* @param clientSecret - OAuth client secret (for confidential clients)
|
|
76
|
+
* @param redirectUri - Redirect URI (must match authorization request)
|
|
77
|
+
* @param resource - Resource indicator (RFC 8707)
|
|
78
|
+
*/
|
|
79
|
+
exchangeCodeForToken(options: {
|
|
80
|
+
code: string;
|
|
81
|
+
pkce: PKCEParams;
|
|
82
|
+
tokenEndpoint: string;
|
|
83
|
+
clientId: string;
|
|
84
|
+
clientSecret?: string;
|
|
85
|
+
redirectUri: string;
|
|
86
|
+
resource?: string;
|
|
87
|
+
}): Promise<TokenResponse>;
|
|
88
|
+
/**
|
|
89
|
+
* Refresh access token
|
|
90
|
+
*
|
|
91
|
+
* @param refreshToken - Refresh token
|
|
92
|
+
* @param tokenEndpoint - Token endpoint
|
|
93
|
+
* @param clientId - OAuth client ID
|
|
94
|
+
* @param clientSecret - OAuth client secret
|
|
95
|
+
* @param scope - Optional: request different scopes
|
|
96
|
+
* @param resource - Resource indicator (RFC 8707)
|
|
97
|
+
*/
|
|
98
|
+
refreshToken(options: {
|
|
99
|
+
refreshToken: string;
|
|
100
|
+
tokenEndpoint: string;
|
|
101
|
+
clientId: string;
|
|
102
|
+
clientSecret?: string;
|
|
103
|
+
scope?: string;
|
|
104
|
+
resource?: string;
|
|
105
|
+
}): Promise<TokenResponse>;
|
|
106
|
+
/**
|
|
107
|
+
* Get client credentials token (for server-to-server)
|
|
108
|
+
*
|
|
109
|
+
* @param tokenEndpoint - Token endpoint
|
|
110
|
+
* @param clientId - OAuth client ID
|
|
111
|
+
* @param clientSecret - OAuth client secret
|
|
112
|
+
* @param scope - Requested scopes
|
|
113
|
+
* @param resource - Resource indicator (RFC 8707)
|
|
114
|
+
*/
|
|
115
|
+
getClientCredentialsToken(options: {
|
|
116
|
+
tokenEndpoint: string;
|
|
117
|
+
clientId: string;
|
|
118
|
+
clientSecret: string;
|
|
119
|
+
scope?: string;
|
|
120
|
+
resource?: string;
|
|
121
|
+
}): Promise<TokenResponse>;
|
|
122
|
+
/**
|
|
123
|
+
* Revoke token (access or refresh)
|
|
124
|
+
*
|
|
125
|
+
* @param token - Token to revoke
|
|
126
|
+
* @param revocationEndpoint - Revocation endpoint
|
|
127
|
+
* @param clientId - OAuth client ID
|
|
128
|
+
* @param clientSecret - OAuth client secret
|
|
129
|
+
* @param tokenTypeHint - 'access_token' or 'refresh_token'
|
|
130
|
+
*/
|
|
131
|
+
revokeToken(options: {
|
|
132
|
+
token: string;
|
|
133
|
+
revocationEndpoint: string;
|
|
134
|
+
clientId: string;
|
|
135
|
+
clientSecret?: string;
|
|
136
|
+
tokenTypeHint?: 'access_token' | 'refresh_token';
|
|
137
|
+
}): Promise<void>;
|
|
138
|
+
/**
|
|
139
|
+
* Make token request
|
|
140
|
+
*/
|
|
141
|
+
private tokenRequest;
|
|
142
|
+
/**
|
|
143
|
+
* Fetch metadata from URL
|
|
144
|
+
*/
|
|
145
|
+
private fetchMetadata;
|
|
146
|
+
/**
|
|
147
|
+
* Generate random state for CSRF protection
|
|
148
|
+
*/
|
|
149
|
+
private generateState;
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/auth/client.ts"],"names":[],"mappings":"AACA,OAAO,EACL,yBAAyB,EACzB,2BAA2B,EAC3B,yBAAyB,EACzB,0BAA0B,EAC1B,aAAa,EAIb,mBAAmB,EACpB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAsB,UAAU,EAAuB,MAAM,WAAW,CAAC;AAGhF;;;;;;;;;GASG;AAEH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAsB;gBAExB,MAAM,EAAE,mBAAmB;IAIvC;;;;;;;;;OASG;IACG,iCAAiC,CACrC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,yBAAyB,CAAC;IAyCrC;;;;;;;;OAQG;IACG,mCAAmC,CACvC,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,2BAA2B,CAAC;IAmDvC;;;;;OAKG;IACG,cAAc,CAClB,oBAAoB,EAAE,MAAM,EAC5B,QAAQ,EAAE,yBAAyB,GAClC,OAAO,CAAC,0BAA0B,CAAC;IAqBtC;;;;;;;;;;;OAWG;IACG,sBAAsB,CAAC,OAAO,EAAE;QACpC,qBAAqB,EAAE,MAAM,CAAC;QAC9B,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,OAAO,CAAC;QACV,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,UAAU,CAAC;KAClB,CAAC;IA+BF;;;;;;;;;;OAUG;IACG,oBAAoB,CAAC,OAAO,EAAE;QAClC,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,UAAU,CAAC;QACjB,aAAa,EAAE,MAAM,CAAC;QACtB,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,aAAa,CAAC;IA6B1B;;;;;;;;;OASG;IACG,YAAY,CAAC,OAAO,EAAE;QAC1B,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;QACtB,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,aAAa,CAAC;IA8B1B;;;;;;;;OAQG;IACG,yBAAyB,CAAC,OAAO,EAAE;QACvC,aAAa,EAAE,MAAM,CAAC;QACtB,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,aAAa,CAAC;IAyB1B;;;;;;;;OAQG;IACG,WAAW,CAAC,OAAO,EAAE;QACzB,KAAK,EAAE,MAAM,CAAC;QACd,kBAAkB,EAAE,MAAM,CAAC;QAC3B,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,aAAa,CAAC,EAAE,cAAc,GAAG,eAAe,CAAC;KAClD,GAAG,OAAO,CAAC,IAAI,CAAC;IAgCjB;;OAEG;YACW,YAAY;IAuB1B;;OAEG;YACW,aAAa;IAa3B;;OAEG;IACH,OAAO,CAAC,aAAa;CAGtB"}
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
2
|
+
import { generatePKCEParams, validatePKCESupport } from './pkce.js';
|
|
3
|
+
import { parseWWWAuthenticateHeader, getWellKnownMetadataUris } from './server-metadata.js';
|
|
4
|
+
/**
|
|
5
|
+
* OAuth 2.1 Client for MCP
|
|
6
|
+
*
|
|
7
|
+
* Handles:
|
|
8
|
+
* - Protected Resource Metadata discovery (RFC 9728)
|
|
9
|
+
* - Authorization Server Metadata discovery (RFC 8414)
|
|
10
|
+
* - Dynamic Client Registration (RFC 7591)
|
|
11
|
+
* - Authorization Code Flow with PKCE (OAuth 2.1)
|
|
12
|
+
* - Token refresh and revocation
|
|
13
|
+
*/
|
|
14
|
+
export class OAuth2Client {
|
|
15
|
+
config;
|
|
16
|
+
constructor(config) {
|
|
17
|
+
this.config = config;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Discover Protected Resource Metadata (RFC 9728)
|
|
21
|
+
*
|
|
22
|
+
* Tries:
|
|
23
|
+
* 1. WWW-Authenticate header from 401 response
|
|
24
|
+
* 2. Well-known URI at resource path
|
|
25
|
+
* 3. Well-known URI at root
|
|
26
|
+
*
|
|
27
|
+
* @param resourceUrl - URL of the MCP server
|
|
28
|
+
*/
|
|
29
|
+
async discoverProtectedResourceMetadata(resourceUrl) {
|
|
30
|
+
// Step 1: Try making a request to get 401 with WWW-Authenticate header
|
|
31
|
+
try {
|
|
32
|
+
const response = await fetch(resourceUrl, {
|
|
33
|
+
method: 'GET',
|
|
34
|
+
headers: { Accept: 'application/json' },
|
|
35
|
+
});
|
|
36
|
+
if (response.status === 401) {
|
|
37
|
+
const wwwAuth = response.headers.get('WWW-Authenticate');
|
|
38
|
+
if (wwwAuth) {
|
|
39
|
+
const parsed = parseWWWAuthenticateHeader(wwwAuth);
|
|
40
|
+
if (parsed?.resourceMetadata) {
|
|
41
|
+
// Found metadata URL in header
|
|
42
|
+
return await this.fetchMetadata(parsed.resourceMetadata);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
// Ignore errors, try well-known URIs
|
|
49
|
+
}
|
|
50
|
+
// Step 2: Try well-known URIs
|
|
51
|
+
const url = new URL(resourceUrl);
|
|
52
|
+
const wellKnownUris = getWellKnownMetadataUris(url);
|
|
53
|
+
for (const uri of wellKnownUris) {
|
|
54
|
+
try {
|
|
55
|
+
return await this.fetchMetadata(uri);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
// Try next URI
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
throw new Error(`Failed to discover protected resource metadata for ${resourceUrl}. ` +
|
|
63
|
+
'Server must implement RFC 9728 (Protected Resource Metadata).');
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Discover Authorization Server Metadata (RFC 8414)
|
|
67
|
+
*
|
|
68
|
+
* Supports both:
|
|
69
|
+
* - OAuth 2.0 Authorization Server Metadata (RFC 8414)
|
|
70
|
+
* - OpenID Connect Discovery 1.0
|
|
71
|
+
*
|
|
72
|
+
* @param issuer - Authorization server issuer URL
|
|
73
|
+
*/
|
|
74
|
+
async discoverAuthorizationServerMetadata(issuer) {
|
|
75
|
+
const issuerUrl = new URL(issuer);
|
|
76
|
+
const wellKnownUrls = [];
|
|
77
|
+
// For issuer URLs with path components
|
|
78
|
+
if (issuerUrl.pathname && issuerUrl.pathname !== '/') {
|
|
79
|
+
const path = issuerUrl.pathname;
|
|
80
|
+
// OAuth 2.0 with path insertion
|
|
81
|
+
wellKnownUrls.push(`${issuerUrl.origin}/.well-known/oauth-authorization-server${path}`);
|
|
82
|
+
// OpenID Connect with path insertion
|
|
83
|
+
wellKnownUrls.push(`${issuerUrl.origin}/.well-known/openid-configuration${path}`);
|
|
84
|
+
// OpenID Connect with path appending
|
|
85
|
+
wellKnownUrls.push(`${issuer}/.well-known/openid-configuration`);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
// For issuer URLs without path components
|
|
89
|
+
wellKnownUrls.push(`${issuerUrl.origin}/.well-known/oauth-authorization-server`);
|
|
90
|
+
wellKnownUrls.push(`${issuerUrl.origin}/.well-known/openid-configuration`);
|
|
91
|
+
}
|
|
92
|
+
// Try each URL
|
|
93
|
+
for (const url of wellKnownUrls) {
|
|
94
|
+
try {
|
|
95
|
+
const metadata = await this.fetchMetadata(url);
|
|
96
|
+
// Validate PKCE support (REQUIRED by OAuth 2.1)
|
|
97
|
+
if (!validatePKCESupport(metadata.code_challenge_methods_supported)) {
|
|
98
|
+
throw new Error('Authorization server does not support PKCE (S256). ' +
|
|
99
|
+
'OAuth 2.1 requires PKCE support. Cannot proceed.');
|
|
100
|
+
}
|
|
101
|
+
return metadata;
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
// Try next URL
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
throw new Error(`Failed to discover authorization server metadata for ${issuer}. ` +
|
|
109
|
+
'Server must implement RFC 8414 or OpenID Connect Discovery.');
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Register client dynamically (RFC 7591)
|
|
113
|
+
*
|
|
114
|
+
* @param registrationEndpoint - Client registration endpoint
|
|
115
|
+
* @param metadata - Client metadata
|
|
116
|
+
*/
|
|
117
|
+
async registerClient(registrationEndpoint, metadata) {
|
|
118
|
+
const response = await fetch(registrationEndpoint, {
|
|
119
|
+
method: 'POST',
|
|
120
|
+
headers: {
|
|
121
|
+
'Content-Type': 'application/json',
|
|
122
|
+
'Accept': 'application/json',
|
|
123
|
+
},
|
|
124
|
+
body: JSON.stringify(metadata),
|
|
125
|
+
});
|
|
126
|
+
if (!response.ok) {
|
|
127
|
+
const error = await response.json().catch(() => ({}));
|
|
128
|
+
throw new Error(`Client registration failed: ${response.status} - ${error.error_description || error.error || 'Unknown error'}`);
|
|
129
|
+
}
|
|
130
|
+
const result = await response.json();
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Start authorization flow
|
|
135
|
+
*
|
|
136
|
+
* Generates authorization URL with PKCE parameters
|
|
137
|
+
*
|
|
138
|
+
* @param authzEndpoint - Authorization endpoint
|
|
139
|
+
* @param clientId - OAuth client ID
|
|
140
|
+
* @param redirectUri - Redirect URI
|
|
141
|
+
* @param scope - Requested scopes
|
|
142
|
+
* @param resource - Resource indicator (RFC 8707)
|
|
143
|
+
* @returns Authorization URL and PKCE parameters (store for token exchange)
|
|
144
|
+
*/
|
|
145
|
+
async startAuthorizationFlow(options) {
|
|
146
|
+
// Generate PKCE parameters (S256 required by OAuth 2.1)
|
|
147
|
+
const pkce = generatePKCEParams('S256');
|
|
148
|
+
// Generate state for CSRF protection
|
|
149
|
+
const state = options.state || this.generateState();
|
|
150
|
+
// Build authorization URL
|
|
151
|
+
const params = new URLSearchParams({
|
|
152
|
+
response_type: 'code',
|
|
153
|
+
client_id: options.clientId,
|
|
154
|
+
redirect_uri: options.redirectUri,
|
|
155
|
+
state,
|
|
156
|
+
code_challenge: pkce.code_challenge,
|
|
157
|
+
code_challenge_method: pkce.code_challenge_method,
|
|
158
|
+
});
|
|
159
|
+
if (options.scope) {
|
|
160
|
+
params.append('scope', options.scope);
|
|
161
|
+
}
|
|
162
|
+
if (options.resource) {
|
|
163
|
+
// RFC 8707 - Resource Indicators
|
|
164
|
+
params.append('resource', options.resource);
|
|
165
|
+
}
|
|
166
|
+
const authUrl = `${options.authorizationEndpoint}?${params.toString()}`;
|
|
167
|
+
return { authUrl, state, pkce };
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Exchange authorization code for access token
|
|
171
|
+
*
|
|
172
|
+
* @param code - Authorization code from callback
|
|
173
|
+
* @param pkce - PKCE parameters from startAuthorizationFlow
|
|
174
|
+
* @param tokenEndpoint - Token endpoint
|
|
175
|
+
* @param clientId - OAuth client ID
|
|
176
|
+
* @param clientSecret - OAuth client secret (for confidential clients)
|
|
177
|
+
* @param redirectUri - Redirect URI (must match authorization request)
|
|
178
|
+
* @param resource - Resource indicator (RFC 8707)
|
|
179
|
+
*/
|
|
180
|
+
async exchangeCodeForToken(options) {
|
|
181
|
+
const params = new URLSearchParams({
|
|
182
|
+
grant_type: 'authorization_code',
|
|
183
|
+
code: options.code,
|
|
184
|
+
redirect_uri: options.redirectUri,
|
|
185
|
+
client_id: options.clientId,
|
|
186
|
+
code_verifier: options.pkce.code_verifier,
|
|
187
|
+
});
|
|
188
|
+
if (options.resource) {
|
|
189
|
+
params.append('resource', options.resource);
|
|
190
|
+
}
|
|
191
|
+
const headers = {
|
|
192
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
193
|
+
'Accept': 'application/json',
|
|
194
|
+
};
|
|
195
|
+
// Client authentication
|
|
196
|
+
if (options.clientSecret) {
|
|
197
|
+
const credentials = Buffer.from(`${options.clientId}:${options.clientSecret}`).toString('base64');
|
|
198
|
+
headers['Authorization'] = `Basic ${credentials}`;
|
|
199
|
+
}
|
|
200
|
+
return await this.tokenRequest(options.tokenEndpoint, params, headers);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Refresh access token
|
|
204
|
+
*
|
|
205
|
+
* @param refreshToken - Refresh token
|
|
206
|
+
* @param tokenEndpoint - Token endpoint
|
|
207
|
+
* @param clientId - OAuth client ID
|
|
208
|
+
* @param clientSecret - OAuth client secret
|
|
209
|
+
* @param scope - Optional: request different scopes
|
|
210
|
+
* @param resource - Resource indicator (RFC 8707)
|
|
211
|
+
*/
|
|
212
|
+
async refreshToken(options) {
|
|
213
|
+
const params = new URLSearchParams({
|
|
214
|
+
grant_type: 'refresh_token',
|
|
215
|
+
refresh_token: options.refreshToken,
|
|
216
|
+
client_id: options.clientId,
|
|
217
|
+
});
|
|
218
|
+
if (options.scope) {
|
|
219
|
+
params.append('scope', options.scope);
|
|
220
|
+
}
|
|
221
|
+
if (options.resource) {
|
|
222
|
+
params.append('resource', options.resource);
|
|
223
|
+
}
|
|
224
|
+
const headers = {
|
|
225
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
226
|
+
'Accept': 'application/json',
|
|
227
|
+
};
|
|
228
|
+
if (options.clientSecret) {
|
|
229
|
+
const credentials = Buffer.from(`${options.clientId}:${options.clientSecret}`).toString('base64');
|
|
230
|
+
headers['Authorization'] = `Basic ${credentials}`;
|
|
231
|
+
}
|
|
232
|
+
return await this.tokenRequest(options.tokenEndpoint, params, headers);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Get client credentials token (for server-to-server)
|
|
236
|
+
*
|
|
237
|
+
* @param tokenEndpoint - Token endpoint
|
|
238
|
+
* @param clientId - OAuth client ID
|
|
239
|
+
* @param clientSecret - OAuth client secret
|
|
240
|
+
* @param scope - Requested scopes
|
|
241
|
+
* @param resource - Resource indicator (RFC 8707)
|
|
242
|
+
*/
|
|
243
|
+
async getClientCredentialsToken(options) {
|
|
244
|
+
const params = new URLSearchParams({
|
|
245
|
+
grant_type: 'client_credentials',
|
|
246
|
+
client_id: options.clientId,
|
|
247
|
+
});
|
|
248
|
+
if (options.scope) {
|
|
249
|
+
params.append('scope', options.scope);
|
|
250
|
+
}
|
|
251
|
+
if (options.resource) {
|
|
252
|
+
params.append('resource', options.resource);
|
|
253
|
+
}
|
|
254
|
+
const headers = {
|
|
255
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
256
|
+
'Accept': 'application/json',
|
|
257
|
+
'Authorization': `Basic ${Buffer.from(`${options.clientId}:${options.clientSecret}`).toString('base64')}`,
|
|
258
|
+
};
|
|
259
|
+
return await this.tokenRequest(options.tokenEndpoint, params, headers);
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Revoke token (access or refresh)
|
|
263
|
+
*
|
|
264
|
+
* @param token - Token to revoke
|
|
265
|
+
* @param revocationEndpoint - Revocation endpoint
|
|
266
|
+
* @param clientId - OAuth client ID
|
|
267
|
+
* @param clientSecret - OAuth client secret
|
|
268
|
+
* @param tokenTypeHint - 'access_token' or 'refresh_token'
|
|
269
|
+
*/
|
|
270
|
+
async revokeToken(options) {
|
|
271
|
+
const params = new URLSearchParams({
|
|
272
|
+
token: options.token,
|
|
273
|
+
client_id: options.clientId,
|
|
274
|
+
});
|
|
275
|
+
if (options.tokenTypeHint) {
|
|
276
|
+
params.append('token_type_hint', options.tokenTypeHint);
|
|
277
|
+
}
|
|
278
|
+
const headers = {
|
|
279
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
280
|
+
};
|
|
281
|
+
if (options.clientSecret) {
|
|
282
|
+
const credentials = Buffer.from(`${options.clientId}:${options.clientSecret}`).toString('base64');
|
|
283
|
+
headers['Authorization'] = `Basic ${credentials}`;
|
|
284
|
+
}
|
|
285
|
+
const response = await fetch(options.revocationEndpoint, {
|
|
286
|
+
method: 'POST',
|
|
287
|
+
headers,
|
|
288
|
+
body: params.toString(),
|
|
289
|
+
});
|
|
290
|
+
if (!response.ok) {
|
|
291
|
+
throw new Error(`Token revocation failed: ${response.status} ${response.statusText}`);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Make token request
|
|
296
|
+
*/
|
|
297
|
+
async tokenRequest(endpoint, params, headers) {
|
|
298
|
+
const response = await fetch(endpoint, {
|
|
299
|
+
method: 'POST',
|
|
300
|
+
headers,
|
|
301
|
+
body: params.toString(),
|
|
302
|
+
});
|
|
303
|
+
const data = await response.json();
|
|
304
|
+
if (!response.ok) {
|
|
305
|
+
const error = data;
|
|
306
|
+
throw new Error(`Token request failed: ${error.error} - ${error.error_description || 'Unknown error'}`);
|
|
307
|
+
}
|
|
308
|
+
return data;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Fetch metadata from URL
|
|
312
|
+
*/
|
|
313
|
+
async fetchMetadata(url) {
|
|
314
|
+
const response = await fetch(url, {
|
|
315
|
+
method: 'GET',
|
|
316
|
+
headers: { Accept: 'application/json' },
|
|
317
|
+
});
|
|
318
|
+
if (!response.ok) {
|
|
319
|
+
throw new Error(`Failed to fetch metadata from ${url}: ${response.status}`);
|
|
320
|
+
}
|
|
321
|
+
return await response.json();
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Generate random state for CSRF protection
|
|
325
|
+
*/
|
|
326
|
+
generateState() {
|
|
327
|
+
return crypto.randomBytes(16).toString('hex');
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/auth/client.ts"],"names":[],"mappings":"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"}
|