@shin1ohno/sage 0.3.0 → 0.5.5

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.
Files changed (95) hide show
  1. package/dist/cli/http-server-with-config.d.ts +38 -0
  2. package/dist/cli/http-server-with-config.d.ts.map +1 -0
  3. package/dist/cli/http-server-with-config.js +477 -0
  4. package/dist/cli/http-server-with-config.js.map +1 -0
  5. package/dist/cli/http-server.d.ts +74 -0
  6. package/dist/cli/http-server.d.ts.map +1 -0
  7. package/dist/cli/http-server.js +407 -0
  8. package/dist/cli/http-server.js.map +1 -0
  9. package/dist/cli/jwt-middleware.d.ts +36 -0
  10. package/dist/cli/jwt-middleware.d.ts.map +1 -0
  11. package/dist/cli/jwt-middleware.js +99 -0
  12. package/dist/cli/jwt-middleware.js.map +1 -0
  13. package/dist/cli/main-entry.d.ts +45 -0
  14. package/dist/cli/main-entry.d.ts.map +1 -0
  15. package/dist/cli/main-entry.js +192 -0
  16. package/dist/cli/main-entry.js.map +1 -0
  17. package/dist/cli/mcp-handler.d.ts +56 -0
  18. package/dist/cli/mcp-handler.d.ts.map +1 -0
  19. package/dist/cli/mcp-handler.js +2189 -0
  20. package/dist/cli/mcp-handler.js.map +1 -0
  21. package/dist/cli/parser.d.ts +45 -0
  22. package/dist/cli/parser.d.ts.map +1 -0
  23. package/dist/cli/parser.js +172 -0
  24. package/dist/cli/parser.js.map +1 -0
  25. package/dist/cli/remote-config-loader.d.ts +89 -0
  26. package/dist/cli/remote-config-loader.d.ts.map +1 -0
  27. package/dist/cli/remote-config-loader.js +129 -0
  28. package/dist/cli/remote-config-loader.js.map +1 -0
  29. package/dist/cli/secret-auth.d.ts +47 -0
  30. package/dist/cli/secret-auth.d.ts.map +1 -0
  31. package/dist/cli/secret-auth.js +165 -0
  32. package/dist/cli/secret-auth.js.map +1 -0
  33. package/dist/cli/sse-stream-handler.d.ts +45 -0
  34. package/dist/cli/sse-stream-handler.d.ts.map +1 -0
  35. package/dist/cli/sse-stream-handler.js +125 -0
  36. package/dist/cli/sse-stream-handler.js.map +1 -0
  37. package/dist/index.js +897 -209
  38. package/dist/index.js.map +1 -1
  39. package/dist/integrations/calendar-event-creator.d.ts +152 -0
  40. package/dist/integrations/calendar-event-creator.d.ts.map +1 -0
  41. package/dist/integrations/calendar-event-creator.js +507 -0
  42. package/dist/integrations/calendar-event-creator.js.map +1 -0
  43. package/dist/integrations/calendar-event-deleter.d.ts +137 -0
  44. package/dist/integrations/calendar-event-deleter.d.ts.map +1 -0
  45. package/dist/integrations/calendar-event-deleter.js +378 -0
  46. package/dist/integrations/calendar-event-deleter.js.map +1 -0
  47. package/dist/integrations/calendar-event-response.d.ts +213 -0
  48. package/dist/integrations/calendar-event-response.d.ts.map +1 -0
  49. package/dist/integrations/calendar-event-response.js +560 -0
  50. package/dist/integrations/calendar-event-response.js.map +1 -0
  51. package/dist/integrations/calendar-service.d.ts +66 -1
  52. package/dist/integrations/calendar-service.d.ts.map +1 -1
  53. package/dist/integrations/calendar-service.js +223 -0
  54. package/dist/integrations/calendar-service.js.map +1 -1
  55. package/dist/oauth/client-store.d.ts +36 -0
  56. package/dist/oauth/client-store.d.ts.map +1 -0
  57. package/dist/oauth/client-store.js +119 -0
  58. package/dist/oauth/client-store.js.map +1 -0
  59. package/dist/oauth/code-store.d.ts +48 -0
  60. package/dist/oauth/code-store.d.ts.map +1 -0
  61. package/dist/oauth/code-store.js +89 -0
  62. package/dist/oauth/code-store.js.map +1 -0
  63. package/dist/oauth/index.d.ts +13 -0
  64. package/dist/oauth/index.d.ts.map +1 -0
  65. package/dist/oauth/index.js +21 -0
  66. package/dist/oauth/index.js.map +1 -0
  67. package/dist/oauth/oauth-handler.d.ts +101 -0
  68. package/dist/oauth/oauth-handler.d.ts.map +1 -0
  69. package/dist/oauth/oauth-handler.js +577 -0
  70. package/dist/oauth/oauth-handler.js.map +1 -0
  71. package/dist/oauth/oauth-server.d.ts +165 -0
  72. package/dist/oauth/oauth-server.d.ts.map +1 -0
  73. package/dist/oauth/oauth-server.js +489 -0
  74. package/dist/oauth/oauth-server.js.map +1 -0
  75. package/dist/oauth/pkce.d.ts +48 -0
  76. package/dist/oauth/pkce.d.ts.map +1 -0
  77. package/dist/oauth/pkce.js +106 -0
  78. package/dist/oauth/pkce.js.map +1 -0
  79. package/dist/oauth/refresh-token-store.d.ts +45 -0
  80. package/dist/oauth/refresh-token-store.d.ts.map +1 -0
  81. package/dist/oauth/refresh-token-store.js +98 -0
  82. package/dist/oauth/refresh-token-store.js.map +1 -0
  83. package/dist/oauth/token-service.d.ts +46 -0
  84. package/dist/oauth/token-service.d.ts.map +1 -0
  85. package/dist/oauth/token-service.js +199 -0
  86. package/dist/oauth/token-service.js.map +1 -0
  87. package/dist/oauth/types.d.ts +269 -0
  88. package/dist/oauth/types.d.ts.map +1 -0
  89. package/dist/oauth/types.js +53 -0
  90. package/dist/oauth/types.js.map +1 -0
  91. package/dist/version.d.ts +9 -0
  92. package/dist/version.d.ts.map +1 -0
  93. package/dist/version.js +11 -0
  94. package/dist/version.js.map +1 -0
  95. package/package.json +1 -1
@@ -0,0 +1,489 @@
1
+ /**
2
+ * OAuth 2.1 Server
3
+ * Requirements: 21-31 (OAuth 2.1 Authentication)
4
+ *
5
+ * Main OAuth server that coordinates all OAuth components and handles requests.
6
+ */
7
+ import { randomBytes, createHash } from 'crypto';
8
+ import { SCOPE_DEFINITIONS, DEFAULT_TOKEN_EXPIRY, CLAUDE_CALLBACK_URLS, } from './types.js';
9
+ import { createTokenService, generateKeyPair } from './token-service.js';
10
+ import { createAuthorizationCodeStore } from './code-store.js';
11
+ import { createRefreshTokenStore } from './refresh-token-store.js';
12
+ import { createClientStore } from './client-store.js';
13
+ import { verifyCodeChallenge } from './pkce.js';
14
+ /**
15
+ * In-memory Session Store
16
+ */
17
+ class InMemorySessionStore {
18
+ sessions = new Map();
19
+ sessionExpiryMs = 24 * 60 * 60 * 1000; // 24 hours
20
+ createSession(userId) {
21
+ const sessionId = randomBytes(32).toString('hex');
22
+ const now = Date.now();
23
+ const session = {
24
+ sessionId,
25
+ userId,
26
+ createdAt: now,
27
+ expiresAt: now + this.sessionExpiryMs,
28
+ };
29
+ this.sessions.set(sessionId, session);
30
+ return session;
31
+ }
32
+ getSession(sessionId) {
33
+ const session = this.sessions.get(sessionId);
34
+ if (!session)
35
+ return null;
36
+ if (Date.now() > session.expiresAt) {
37
+ this.sessions.delete(sessionId);
38
+ return null;
39
+ }
40
+ return session;
41
+ }
42
+ deleteSession(sessionId) {
43
+ this.sessions.delete(sessionId);
44
+ }
45
+ }
46
+ /**
47
+ * OAuth Server Class
48
+ */
49
+ export class OAuthServer {
50
+ config;
51
+ tokenService;
52
+ codeStore;
53
+ refreshTokenStore;
54
+ clientStore;
55
+ sessionStore;
56
+ users;
57
+ pendingAuthRequests = new Map();
58
+ loginAttempts = new Map();
59
+ privateKey;
60
+ publicKey;
61
+ constructor(config, keys) {
62
+ this.config = config;
63
+ this.privateKey = keys?.privateKey || '';
64
+ this.publicKey = keys?.publicKey || '';
65
+ // Parse expiry durations to seconds
66
+ const refreshTokenExpirySec = this.parseExpiryToSeconds(config.refreshTokenExpiry || DEFAULT_TOKEN_EXPIRY.refreshToken);
67
+ const authCodeExpirySec = this.parseExpiryToSeconds(config.authorizationCodeExpiry || DEFAULT_TOKEN_EXPIRY.authorizationCode);
68
+ // Initialize stores
69
+ this.codeStore = createAuthorizationCodeStore({ expirySeconds: authCodeExpirySec });
70
+ this.refreshTokenStore = createRefreshTokenStore({ expirySeconds: refreshTokenExpirySec });
71
+ this.clientStore = createClientStore({
72
+ allowedRedirectUris: [...(config.allowedRedirectUris || []), ...CLAUDE_CALLBACK_URLS],
73
+ });
74
+ this.sessionStore = new InMemorySessionStore();
75
+ // Initialize token service (will be updated when keys are available)
76
+ this.tokenService = createTokenService({
77
+ issuer: config.issuer,
78
+ privateKey: this.privateKey,
79
+ publicKey: this.publicKey,
80
+ accessTokenExpiry: config.accessTokenExpiry || DEFAULT_TOKEN_EXPIRY.accessToken,
81
+ });
82
+ // Store users
83
+ this.users = new Map();
84
+ for (const user of config.users || []) {
85
+ this.users.set(user.username, user);
86
+ }
87
+ }
88
+ /**
89
+ * Initialize the server with generated keys if not provided
90
+ */
91
+ async initialize() {
92
+ if (!this.privateKey || !this.publicKey) {
93
+ const keys = await generateKeyPair();
94
+ this.privateKey = keys.privateKey;
95
+ this.publicKey = keys.publicKey;
96
+ // Recreate token service with new keys
97
+ this.tokenService = createTokenService({
98
+ issuer: this.config.issuer,
99
+ privateKey: this.privateKey,
100
+ publicKey: this.publicKey,
101
+ accessTokenExpiry: this.config.accessTokenExpiry || DEFAULT_TOKEN_EXPIRY.accessToken,
102
+ });
103
+ }
104
+ }
105
+ parseExpiryToSeconds(expiry) {
106
+ const match = expiry.match(/^(\d+)([smhdw])$/);
107
+ if (!match)
108
+ return 3600;
109
+ const value = parseInt(match[1], 10);
110
+ const unit = match[2];
111
+ switch (unit) {
112
+ case 's': return value;
113
+ case 'm': return value * 60;
114
+ case 'h': return value * 3600;
115
+ case 'd': return value * 86400;
116
+ case 'w': return value * 604800;
117
+ default: return 3600;
118
+ }
119
+ }
120
+ /**
121
+ * Get Protected Resource Metadata (RFC 9728)
122
+ * Requirement 22.1-22.3
123
+ */
124
+ getProtectedResourceMetadata() {
125
+ return {
126
+ resource: this.config.issuer,
127
+ authorization_servers: [this.config.issuer],
128
+ scopes_supported: Object.keys(SCOPE_DEFINITIONS),
129
+ bearer_methods_supported: ['header'],
130
+ };
131
+ }
132
+ /**
133
+ * Get Authorization Server Metadata (RFC 8414)
134
+ * Requirement 23.1-23.9
135
+ */
136
+ getAuthorizationServerMetadata() {
137
+ return {
138
+ issuer: this.config.issuer,
139
+ authorization_endpoint: `${this.config.issuer}/oauth/authorize`,
140
+ token_endpoint: `${this.config.issuer}/oauth/token`,
141
+ registration_endpoint: `${this.config.issuer}/oauth/register`,
142
+ scopes_supported: Object.keys(SCOPE_DEFINITIONS),
143
+ response_types_supported: ['code'],
144
+ response_modes_supported: ['query'],
145
+ grant_types_supported: ['authorization_code', 'refresh_token'],
146
+ token_endpoint_auth_methods_supported: ['none', 'client_secret_post'],
147
+ code_challenge_methods_supported: ['S256'],
148
+ service_documentation: 'https://github.com/shin1ohno/sage',
149
+ };
150
+ }
151
+ /**
152
+ * Get WWW-Authenticate header for 401 responses
153
+ * Requirement 22.4, 22.5
154
+ */
155
+ getWWWAuthenticateHeader() {
156
+ return `Bearer realm="sage", resource_metadata="${this.config.issuer}/.well-known/oauth-protected-resource"`;
157
+ }
158
+ /**
159
+ * Register a new client (Dynamic Client Registration)
160
+ * Requirement 24.1-24.7
161
+ */
162
+ async registerClient(request) {
163
+ return this.clientStore.registerClient(request);
164
+ }
165
+ /**
166
+ * Get a registered client
167
+ */
168
+ async getClient(clientId) {
169
+ return this.clientStore.getClient(clientId);
170
+ }
171
+ /**
172
+ * Delete a client (Requirement 24.8)
173
+ */
174
+ async deleteClient(clientId) {
175
+ // Also revoke all refresh tokens for this client
176
+ await this.refreshTokenStore.revokeAllForClient(clientId);
177
+ return this.clientStore.deleteClient(clientId);
178
+ }
179
+ /**
180
+ * Validate an authorization request
181
+ * Requirement 25.1-25.8
182
+ */
183
+ async validateAuthorizationRequest(request) {
184
+ // Requirement 25.2: Only support response_type=code
185
+ if (request.response_type !== 'code') {
186
+ return {
187
+ valid: false,
188
+ error: {
189
+ error: 'unsupported_response_type',
190
+ error_description: 'Only response_type=code is supported',
191
+ state: request.state,
192
+ },
193
+ };
194
+ }
195
+ // Requirement 25.3: client_id is required
196
+ const client = await this.clientStore.getClient(request.client_id);
197
+ if (!client) {
198
+ return {
199
+ valid: false,
200
+ error: {
201
+ error: 'invalid_client',
202
+ error_description: 'Unknown client_id',
203
+ state: request.state,
204
+ },
205
+ };
206
+ }
207
+ // Requirement 25.4: Validate redirect_uri
208
+ if (!await this.clientStore.isValidRedirectUri(request.client_id, request.redirect_uri)) {
209
+ return {
210
+ valid: false,
211
+ error: {
212
+ error: 'invalid_request',
213
+ error_description: 'Invalid redirect_uri',
214
+ state: request.state,
215
+ },
216
+ };
217
+ }
218
+ // Requirement 25.5, 25.6: PKCE is required, only S256
219
+ if (!request.code_challenge) {
220
+ return {
221
+ valid: false,
222
+ error: {
223
+ error: 'invalid_request',
224
+ error_description: 'code_challenge is required',
225
+ state: request.state,
226
+ },
227
+ };
228
+ }
229
+ if (request.code_challenge_method !== 'S256') {
230
+ return {
231
+ valid: false,
232
+ error: {
233
+ error: 'invalid_request',
234
+ error_description: 'Only code_challenge_method=S256 is supported',
235
+ state: request.state,
236
+ },
237
+ };
238
+ }
239
+ // Requirement 25.7: state is required
240
+ if (!request.state) {
241
+ return {
242
+ valid: false,
243
+ error: {
244
+ error: 'invalid_request',
245
+ error_description: 'state is required',
246
+ },
247
+ };
248
+ }
249
+ return { valid: true, client };
250
+ }
251
+ /**
252
+ * Store a pending authorization request (for consent flow)
253
+ */
254
+ storePendingAuthRequest(requestId, request, client) {
255
+ this.pendingAuthRequests.set(requestId, {
256
+ request,
257
+ client,
258
+ createdAt: Date.now(),
259
+ });
260
+ // Cleanup old requests (older than 10 minutes)
261
+ const cutoff = Date.now() - 10 * 60 * 1000;
262
+ for (const [id, pending] of this.pendingAuthRequests.entries()) {
263
+ if (pending.createdAt < cutoff) {
264
+ this.pendingAuthRequests.delete(id);
265
+ }
266
+ }
267
+ }
268
+ /**
269
+ * Get a pending authorization request
270
+ */
271
+ getPendingAuthRequest(requestId) {
272
+ return this.pendingAuthRequests.get(requestId) || null;
273
+ }
274
+ /**
275
+ * Complete authorization and generate code
276
+ * Requirement 25.9, 25.10
277
+ */
278
+ async completeAuthorization(request, userId) {
279
+ const code = await this.codeStore.generateCode({
280
+ clientId: request.client_id,
281
+ redirectUri: request.redirect_uri,
282
+ scope: request.scope || '',
283
+ codeChallenge: request.code_challenge,
284
+ codeChallengeMethod: request.code_challenge_method,
285
+ userId,
286
+ resource: request.resource,
287
+ });
288
+ return code;
289
+ }
290
+ /**
291
+ * Exchange authorization code for tokens
292
+ * Requirement 26.1-26.7
293
+ */
294
+ async exchangeAuthorizationCode(code, clientId, redirectUri, codeVerifier, resource) {
295
+ // Consume code (marks it as used)
296
+ const codeResult = await this.codeStore.consumeCode(code, clientId);
297
+ if (!codeResult.valid || !codeResult.codeData) {
298
+ return {
299
+ success: false,
300
+ error: {
301
+ error: 'invalid_grant',
302
+ error_description: 'Invalid or expired authorization code',
303
+ },
304
+ };
305
+ }
306
+ // Verify redirect_uri matches
307
+ if (codeResult.codeData.redirect_uri !== redirectUri) {
308
+ return {
309
+ success: false,
310
+ error: {
311
+ error: 'invalid_grant',
312
+ error_description: 'redirect_uri does not match',
313
+ },
314
+ };
315
+ }
316
+ // Verify PKCE code_verifier (Requirement 26.4)
317
+ if (!verifyCodeChallenge(codeVerifier, codeResult.codeData.code_challenge, 'S256')) {
318
+ return {
319
+ success: false,
320
+ error: {
321
+ error: 'invalid_grant',
322
+ error_description: 'Invalid code_verifier',
323
+ },
324
+ };
325
+ }
326
+ // Verify resource if specified (Requirement 26.5)
327
+ if (resource && codeResult.codeData.resource && resource !== codeResult.codeData.resource) {
328
+ return {
329
+ success: false,
330
+ error: {
331
+ error: 'invalid_grant',
332
+ error_description: 'resource does not match',
333
+ },
334
+ };
335
+ }
336
+ // Generate access token
337
+ const accessTokenResponse = await this.tokenService.generateAccessToken({
338
+ clientId,
339
+ userId: codeResult.codeData.user_id,
340
+ scope: codeResult.codeData.scope,
341
+ audience: resource || this.config.issuer,
342
+ });
343
+ // Generate refresh token (Requirement 21.6)
344
+ const refreshToken = await this.refreshTokenStore.generateToken({
345
+ clientId,
346
+ userId: codeResult.codeData.user_id,
347
+ scope: codeResult.codeData.scope,
348
+ });
349
+ return {
350
+ success: true,
351
+ tokens: {
352
+ ...accessTokenResponse,
353
+ refresh_token: refreshToken,
354
+ },
355
+ };
356
+ }
357
+ /**
358
+ * Exchange refresh token for new tokens
359
+ * Requirement 26.3, 26.8
360
+ */
361
+ async exchangeRefreshToken(refreshToken, clientId, scope) {
362
+ // Rotate refresh token (Requirement 26.8)
363
+ const newRefreshToken = await this.refreshTokenStore.rotateToken(refreshToken, clientId);
364
+ if (!newRefreshToken) {
365
+ return {
366
+ success: false,
367
+ error: {
368
+ error: 'invalid_grant',
369
+ error_description: 'Invalid or expired refresh token',
370
+ },
371
+ };
372
+ }
373
+ // Get the original token data before it was rotated
374
+ const tokenResult = await this.refreshTokenStore.validateToken(newRefreshToken, clientId);
375
+ if (!tokenResult.valid || !tokenResult.tokenData) {
376
+ return {
377
+ success: false,
378
+ error: {
379
+ error: 'invalid_grant',
380
+ error_description: 'Invalid refresh token',
381
+ },
382
+ };
383
+ }
384
+ // Use requested scope or original scope
385
+ const effectiveScope = scope || tokenResult.tokenData.scope;
386
+ // Generate new access token
387
+ const accessTokenResponse = await this.tokenService.generateAccessToken({
388
+ clientId,
389
+ userId: tokenResult.tokenData.user_id,
390
+ scope: effectiveScope,
391
+ audience: this.config.issuer,
392
+ });
393
+ return {
394
+ success: true,
395
+ tokens: {
396
+ ...accessTokenResponse,
397
+ refresh_token: newRefreshToken,
398
+ },
399
+ };
400
+ }
401
+ /**
402
+ * Verify an access token
403
+ * Requirement 27.1-27.5
404
+ */
405
+ async verifyAccessToken(token, expectedAudience) {
406
+ return this.tokenService.verifyAccessToken(token, expectedAudience);
407
+ }
408
+ /**
409
+ * Extract token from Authorization header
410
+ * Requirement 27.1
411
+ */
412
+ extractTokenFromHeader(header) {
413
+ return this.tokenService.extractTokenFromHeader(header);
414
+ }
415
+ /**
416
+ * Authenticate a user (Requirement 29.1-29.5)
417
+ */
418
+ async authenticateUser(username, password) {
419
+ // Rate limiting (Requirement 29.5)
420
+ const key = username;
421
+ const attempts = this.loginAttempts.get(key) || { count: 0, lastAttempt: 0 };
422
+ // Reset attempts after 15 minutes
423
+ if (Date.now() - attempts.lastAttempt > 15 * 60 * 1000) {
424
+ attempts.count = 0;
425
+ }
426
+ if (attempts.count >= 5) {
427
+ return { success: false, error: 'Too many login attempts. Please try again later.' };
428
+ }
429
+ const user = this.users.get(username);
430
+ if (!user) {
431
+ attempts.count++;
432
+ attempts.lastAttempt = Date.now();
433
+ this.loginAttempts.set(key, attempts);
434
+ return { success: false, error: 'Invalid username or password' };
435
+ }
436
+ // Verify password (Requirement 29.4: passwords should be hashed)
437
+ // For simplicity, we'll compare against the stored hash
438
+ // In production, use bcrypt or similar
439
+ const passwordHash = createHash('sha256').update(password).digest('hex');
440
+ if (passwordHash !== user.passwordHash) {
441
+ attempts.count++;
442
+ attempts.lastAttempt = Date.now();
443
+ this.loginAttempts.set(key, attempts);
444
+ return { success: false, error: 'Invalid username or password' };
445
+ }
446
+ // Reset login attempts on success
447
+ this.loginAttempts.delete(key);
448
+ // Create session
449
+ const session = this.sessionStore.createSession(user.id);
450
+ return { success: true, session };
451
+ }
452
+ /**
453
+ * Validate a session
454
+ */
455
+ validateSession(sessionId) {
456
+ return this.sessionStore.getSession(sessionId);
457
+ }
458
+ /**
459
+ * Logout user
460
+ */
461
+ logout(sessionId) {
462
+ this.sessionStore.deleteSession(sessionId);
463
+ }
464
+ /**
465
+ * Check if a scope includes another scope
466
+ */
467
+ hasScope(tokenScope, requiredScope) {
468
+ const tokenScopes = tokenScope.split(' ');
469
+ return tokenScopes.includes(requiredScope);
470
+ }
471
+ /**
472
+ * Get scope descriptions for consent UI
473
+ */
474
+ getScopeDescriptions(scopes) {
475
+ return scopes.split(' ').filter(s => s in SCOPE_DEFINITIONS).map(scope => ({
476
+ scope,
477
+ description: SCOPE_DEFINITIONS[scope],
478
+ }));
479
+ }
480
+ }
481
+ /**
482
+ * Create an OAuth Server instance
483
+ */
484
+ export async function createOAuthServer(config) {
485
+ const server = new OAuthServer(config);
486
+ await server.initialize();
487
+ return server;
488
+ }
489
+ //# sourceMappingURL=oauth-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-server.js","sourceRoot":"","sources":["../../src/oauth/oauth-server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * OAuth PKCE (S256) Implementation
3
+ * Requirements: 21.2, 26.4
4
+ *
5
+ * Implements PKCE (Proof Key for Code Exchange) using S256 method.
6
+ * Based on RFC 7636.
7
+ */
8
+ import { CodeChallengeMethod } from './types.js';
9
+ /**
10
+ * Generate a cryptographically random code verifier
11
+ *
12
+ * @param length - Length of the verifier (default: 64, min: 43, max: 128)
13
+ * @returns A random code verifier string
14
+ */
15
+ export declare function generateCodeVerifier(length?: number): string;
16
+ /**
17
+ * Generate a code challenge from a code verifier using S256 method
18
+ *
19
+ * S256: BASE64URL(SHA256(code_verifier))
20
+ *
21
+ * @param codeVerifier - The code verifier to hash
22
+ * @returns Base64URL encoded SHA256 hash of the verifier
23
+ */
24
+ export declare function generateCodeChallenge(codeVerifier: string): string;
25
+ /**
26
+ * Verify a code verifier against a code challenge
27
+ *
28
+ * @param codeVerifier - The code verifier from the token request
29
+ * @param codeChallenge - The code challenge from the authorization request
30
+ * @param method - The code challenge method (only 'S256' is supported)
31
+ * @returns True if the verifier matches the challenge
32
+ */
33
+ export declare function verifyCodeChallenge(codeVerifier: string, codeChallenge: string, method: CodeChallengeMethod): boolean;
34
+ /**
35
+ * Validate code verifier format
36
+ *
37
+ * @param codeVerifier - The code verifier to validate
38
+ * @returns True if the verifier has valid format
39
+ */
40
+ export declare function isValidCodeVerifier(codeVerifier: string): boolean;
41
+ /**
42
+ * Validate code challenge format
43
+ *
44
+ * @param codeChallenge - The code challenge to validate
45
+ * @returns True if the challenge has valid format
46
+ */
47
+ export declare function isValidCodeChallenge(codeChallenge: string): boolean;
48
+ //# sourceMappingURL=pkce.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pkce.d.ts","sourceRoot":"","sources":["../../src/oauth/pkce.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAkBjD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,GAAE,MAAgC,GAAG,MAAM,CAYrF;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CASlE;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAQT;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAajE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAanE"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * OAuth PKCE (S256) Implementation
3
+ * Requirements: 21.2, 26.4
4
+ *
5
+ * Implements PKCE (Proof Key for Code Exchange) using S256 method.
6
+ * Based on RFC 7636.
7
+ */
8
+ import { createHash, randomBytes } from 'crypto';
9
+ /**
10
+ * Characters allowed in code verifier (unreserved characters per RFC 7636)
11
+ */
12
+ const UNRESERVED_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';
13
+ /**
14
+ * Default code verifier length
15
+ */
16
+ const DEFAULT_VERIFIER_LENGTH = 64;
17
+ /**
18
+ * Minimum and maximum verifier length per RFC 7636
19
+ */
20
+ const MIN_VERIFIER_LENGTH = 43;
21
+ const MAX_VERIFIER_LENGTH = 128;
22
+ /**
23
+ * Generate a cryptographically random code verifier
24
+ *
25
+ * @param length - Length of the verifier (default: 64, min: 43, max: 128)
26
+ * @returns A random code verifier string
27
+ */
28
+ export function generateCodeVerifier(length = DEFAULT_VERIFIER_LENGTH) {
29
+ // Clamp length to valid range
30
+ const validLength = Math.max(MIN_VERIFIER_LENGTH, Math.min(MAX_VERIFIER_LENGTH, length));
31
+ const bytes = randomBytes(validLength);
32
+ let verifier = '';
33
+ for (let i = 0; i < validLength; i++) {
34
+ verifier += UNRESERVED_CHARS[bytes[i] % UNRESERVED_CHARS.length];
35
+ }
36
+ return verifier;
37
+ }
38
+ /**
39
+ * Generate a code challenge from a code verifier using S256 method
40
+ *
41
+ * S256: BASE64URL(SHA256(code_verifier))
42
+ *
43
+ * @param codeVerifier - The code verifier to hash
44
+ * @returns Base64URL encoded SHA256 hash of the verifier
45
+ */
46
+ export function generateCodeChallenge(codeVerifier) {
47
+ // Calculate SHA256 hash
48
+ const hash = createHash('sha256').update(codeVerifier, 'ascii').digest();
49
+ // Convert to base64url encoding (no padding)
50
+ const base64 = hash.toString('base64');
51
+ const base64url = base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
52
+ return base64url;
53
+ }
54
+ /**
55
+ * Verify a code verifier against a code challenge
56
+ *
57
+ * @param codeVerifier - The code verifier from the token request
58
+ * @param codeChallenge - The code challenge from the authorization request
59
+ * @param method - The code challenge method (only 'S256' is supported)
60
+ * @returns True if the verifier matches the challenge
61
+ */
62
+ export function verifyCodeChallenge(codeVerifier, codeChallenge, method) {
63
+ if (method !== 'S256') {
64
+ throw new Error('Only S256 code challenge method is supported');
65
+ }
66
+ // Generate challenge from verifier and compare
67
+ const expectedChallenge = generateCodeChallenge(codeVerifier);
68
+ return expectedChallenge === codeChallenge;
69
+ }
70
+ /**
71
+ * Validate code verifier format
72
+ *
73
+ * @param codeVerifier - The code verifier to validate
74
+ * @returns True if the verifier has valid format
75
+ */
76
+ export function isValidCodeVerifier(codeVerifier) {
77
+ if (!codeVerifier) {
78
+ return false;
79
+ }
80
+ // Check length
81
+ if (codeVerifier.length < MIN_VERIFIER_LENGTH || codeVerifier.length > MAX_VERIFIER_LENGTH) {
82
+ return false;
83
+ }
84
+ // Check characters (unreserved characters only)
85
+ const validPattern = /^[A-Za-z0-9\-._~]+$/;
86
+ return validPattern.test(codeVerifier);
87
+ }
88
+ /**
89
+ * Validate code challenge format
90
+ *
91
+ * @param codeChallenge - The code challenge to validate
92
+ * @returns True if the challenge has valid format
93
+ */
94
+ export function isValidCodeChallenge(codeChallenge) {
95
+ if (!codeChallenge) {
96
+ return false;
97
+ }
98
+ // S256 challenge should be base64url encoded SHA256 hash (43 characters)
99
+ if (codeChallenge.length !== 43) {
100
+ return false;
101
+ }
102
+ // Check base64url format (no padding)
103
+ const validPattern = /^[A-Za-z0-9\-_]+$/;
104
+ return validPattern.test(codeChallenge);
105
+ }
106
+ //# sourceMappingURL=pkce.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pkce.js","sourceRoot":"","sources":["../../src/oauth/pkce.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAGjD;;GAEG;AACH,MAAM,gBAAgB,GAAG,oEAAoE,CAAC;AAE9F;;GAEG;AACH,MAAM,uBAAuB,GAAG,EAAE,CAAC;AAEnC;;GAEG;AACH,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAC/B,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEhC;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,SAAiB,uBAAuB;IAC3E,8BAA8B;IAC9B,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,mBAAmB,EAAE,IAAI,CAAC,GAAG,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC,CAAC;IAEzF,MAAM,KAAK,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC;IACvC,IAAI,QAAQ,GAAG,EAAE,CAAC;IAElB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,QAAQ,IAAI,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACnE,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CAAC,YAAoB;IACxD,wBAAwB;IACxB,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;IAEzE,6CAA6C;IAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAEpF,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CACjC,YAAoB,EACpB,aAAqB,EACrB,MAA2B;IAE3B,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAClE,CAAC;IAED,+CAA+C;IAC/C,MAAM,iBAAiB,GAAG,qBAAqB,CAAC,YAAY,CAAC,CAAC;IAC9D,OAAO,iBAAiB,KAAK,aAAa,CAAC;AAC7C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,YAAoB;IACtD,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,eAAe;IACf,IAAI,YAAY,CAAC,MAAM,GAAG,mBAAmB,IAAI,YAAY,CAAC,MAAM,GAAG,mBAAmB,EAAE,CAAC;QAC3F,OAAO,KAAK,CAAC;IACf,CAAC;IAED,gDAAgD;IAChD,MAAM,YAAY,GAAG,qBAAqB,CAAC;IAC3C,OAAO,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;AACzC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,aAAqB;IACxD,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,yEAAyE;IACzE,IAAI,aAAa,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAChC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,sCAAsC;IACtC,MAAM,YAAY,GAAG,mBAAmB,CAAC;IACzC,OAAO,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AAC1C,CAAC"}