@shin1ohno/sage 0.2.4 → 0.5.3

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 (96) 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 +458 -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 +41 -0
  14. package/dist/cli/main-entry.d.ts.map +1 -0
  15. package/dist/cli/main-entry.js +80 -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 +43 -0
  22. package/dist/cli/parser.d.ts.map +1 -0
  23. package/dist/cli/parser.js +162 -0
  24. package/dist/cli/parser.js.map +1 -0
  25. package/dist/cli/remote-config-loader.d.ts +85 -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 +885 -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 +85 -10
  52. package/dist/integrations/calendar-service.d.ts.map +1 -1
  53. package/dist/integrations/calendar-service.js +317 -35
  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 +104 -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 +264 -0
  88. package/dist/oauth/types.d.ts.map +1 -0
  89. package/dist/oauth/types.js +37 -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/manifest.json +12 -20
  96. package/package.json +1 -1
@@ -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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * OAuth Refresh Token Store
3
+ * Requirements: 21.6, 26.3, 26.8
4
+ *
5
+ * Manages refresh token generation, storage, validation, and rotation.
6
+ */
7
+ import { RefreshToken } from './types.js';
8
+ /**
9
+ * Configuration for Refresh Token Store
10
+ */
11
+ export interface RefreshTokenStoreConfig {
12
+ expirySeconds: number;
13
+ }
14
+ /**
15
+ * Options for generating a refresh token
16
+ */
17
+ export interface GenerateRefreshTokenOptions {
18
+ clientId: string;
19
+ userId: string;
20
+ scope: string;
21
+ }
22
+ /**
23
+ * Result of validating a refresh token
24
+ */
25
+ export interface RefreshTokenValidationResult {
26
+ valid: boolean;
27
+ tokenData?: RefreshToken;
28
+ error?: string;
29
+ }
30
+ /**
31
+ * Refresh Token Store Interface
32
+ */
33
+ export interface RefreshTokenStore {
34
+ generateToken(options: GenerateRefreshTokenOptions): Promise<string>;
35
+ validateToken(token: string, clientId: string): Promise<RefreshTokenValidationResult>;
36
+ rotateToken(token: string, clientId: string): Promise<string | null>;
37
+ revokeToken(token: string): Promise<void>;
38
+ revokeAllForClient(clientId: string): Promise<void>;
39
+ cleanup(): Promise<number>;
40
+ }
41
+ /**
42
+ * Create a Refresh Token Store instance
43
+ */
44
+ export declare function createRefreshTokenStore(config: RefreshTokenStoreConfig): RefreshTokenStore;
45
+ //# sourceMappingURL=refresh-token-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refresh-token-store.d.ts","sourceRoot":"","sources":["../../src/oauth/refresh-token-store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC3C,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,YAAY,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,aAAa,CAAC,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACrE,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAAC;IACtF,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACrE,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CAC5B;AA6GD;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,uBAAuB,GAAG,iBAAiB,CAE1F"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * OAuth Refresh Token Store
3
+ * Requirements: 21.6, 26.3, 26.8
4
+ *
5
+ * Manages refresh token generation, storage, validation, and rotation.
6
+ */
7
+ import { randomBytes } from 'crypto';
8
+ /**
9
+ * In-memory Refresh Token Store Implementation
10
+ */
11
+ class InMemoryRefreshTokenStore {
12
+ tokens = new Map();
13
+ config;
14
+ constructor(config) {
15
+ this.config = config;
16
+ }
17
+ async generateToken(options) {
18
+ // Generate secure random token
19
+ const token = randomBytes(32).toString('base64url');
20
+ const now = Date.now();
21
+ const expiresAt = now + this.config.expirySeconds * 1000;
22
+ const tokenData = {
23
+ token,
24
+ client_id: options.clientId,
25
+ user_id: options.userId,
26
+ scope: options.scope,
27
+ created_at: now,
28
+ expires_at: expiresAt,
29
+ rotated: false,
30
+ };
31
+ this.tokens.set(token, tokenData);
32
+ return token;
33
+ }
34
+ async validateToken(token, clientId) {
35
+ const tokenData = this.tokens.get(token);
36
+ if (!tokenData) {
37
+ return { valid: false, error: 'invalid_grant' };
38
+ }
39
+ // Check if token has been rotated
40
+ if (tokenData.rotated) {
41
+ return { valid: false, error: 'invalid_grant' };
42
+ }
43
+ // Check if token has expired
44
+ if (Date.now() > tokenData.expires_at) {
45
+ this.tokens.delete(token);
46
+ return { valid: false, error: 'invalid_grant' };
47
+ }
48
+ // Verify client_id matches
49
+ if (tokenData.client_id !== clientId) {
50
+ return { valid: false, error: 'invalid_grant' };
51
+ }
52
+ return { valid: true, tokenData };
53
+ }
54
+ async rotateToken(token, clientId) {
55
+ const validationResult = await this.validateToken(token, clientId);
56
+ if (!validationResult.valid || !validationResult.tokenData) {
57
+ return null;
58
+ }
59
+ // Mark old token as rotated (Requirement 26.8)
60
+ const oldTokenData = this.tokens.get(token);
61
+ oldTokenData.rotated = true;
62
+ // Generate new token with same scope
63
+ const newToken = await this.generateToken({
64
+ clientId: validationResult.tokenData.client_id,
65
+ userId: validationResult.tokenData.user_id,
66
+ scope: validationResult.tokenData.scope,
67
+ });
68
+ return newToken;
69
+ }
70
+ async revokeToken(token) {
71
+ this.tokens.delete(token);
72
+ }
73
+ async revokeAllForClient(clientId) {
74
+ for (const [token, data] of this.tokens.entries()) {
75
+ if (data.client_id === clientId) {
76
+ this.tokens.delete(token);
77
+ }
78
+ }
79
+ }
80
+ async cleanup() {
81
+ const now = Date.now();
82
+ let cleanedCount = 0;
83
+ for (const [token, data] of this.tokens.entries()) {
84
+ if (data.expires_at < now || data.rotated) {
85
+ this.tokens.delete(token);
86
+ cleanedCount++;
87
+ }
88
+ }
89
+ return cleanedCount;
90
+ }
91
+ }
92
+ /**
93
+ * Create a Refresh Token Store instance
94
+ */
95
+ export function createRefreshTokenStore(config) {
96
+ return new InMemoryRefreshTokenStore(config);
97
+ }
98
+ //# sourceMappingURL=refresh-token-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refresh-token-store.js","sourceRoot":"","sources":["../../src/oauth/refresh-token-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * OAuth Token Service
3
+ * Requirements: 21.4, 21.5, 26.6, 26.7, 27.1-27.5
4
+ *
5
+ * Implements JWT access token generation and verification using RS256 signing.
6
+ */
7
+ import { TokenResponse, VerifyTokenResult } from './types.js';
8
+ /**
9
+ * Token Service Configuration
10
+ */
11
+ export interface TokenServiceConfig {
12
+ issuer: string;
13
+ privateKey: string;
14
+ publicKey: string;
15
+ accessTokenExpiry: string;
16
+ }
17
+ /**
18
+ * Access Token Generation Options
19
+ */
20
+ export interface GenerateAccessTokenOptions {
21
+ clientId: string;
22
+ userId: string;
23
+ scope: string;
24
+ audience: string;
25
+ }
26
+ /**
27
+ * Token Service Interface
28
+ */
29
+ export interface TokenService {
30
+ generateAccessToken(options: GenerateAccessTokenOptions): Promise<TokenResponse>;
31
+ verifyAccessToken(token: string, expectedAudience?: string): Promise<VerifyTokenResult>;
32
+ extractTokenFromHeader(header: string | undefined): string | null;
33
+ }
34
+ /**
35
+ * Create a Token Service instance
36
+ */
37
+ export declare function createTokenService(config: TokenServiceConfig): TokenService;
38
+ /**
39
+ * Generate RSA key pair for JWT signing
40
+ * Requirement: RS256 signing
41
+ */
42
+ export declare function generateKeyPair(): Promise<{
43
+ privateKey: string;
44
+ publicKey: string;
45
+ }>;
46
+ //# sourceMappingURL=token-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-service.d.ts","sourceRoot":"","sources":["../../src/oauth/token-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAqB,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEjF;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,mBAAmB,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACjF,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACxF,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAAC;CACnE;AAgND;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,YAAY,CAE3E;AAED;;;GAGG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAc1F"}
@@ -0,0 +1,199 @@
1
+ /**
2
+ * OAuth Token Service
3
+ * Requirements: 21.4, 21.5, 26.6, 26.7, 27.1-27.5
4
+ *
5
+ * Implements JWT access token generation and verification using RS256 signing.
6
+ */
7
+ import { createSign, createVerify, generateKeyPairSync, randomUUID } from 'crypto';
8
+ /**
9
+ * Parse duration string to seconds
10
+ * Supports: s (seconds), m (minutes), h (hours), d (days), w (weeks)
11
+ */
12
+ function parseDuration(duration) {
13
+ const match = duration.match(/^(\d+)([smhdw])$/);
14
+ if (!match) {
15
+ throw new Error(`Invalid duration format: ${duration}`);
16
+ }
17
+ const value = parseInt(match[1], 10);
18
+ const unit = match[2];
19
+ switch (unit) {
20
+ case 's':
21
+ return value;
22
+ case 'm':
23
+ return value * 60;
24
+ case 'h':
25
+ return value * 3600;
26
+ case 'd':
27
+ return value * 86400;
28
+ case 'w':
29
+ return value * 604800;
30
+ default:
31
+ throw new Error(`Unknown duration unit: ${unit}`);
32
+ }
33
+ }
34
+ /**
35
+ * Base64URL encode a string
36
+ */
37
+ function base64UrlEncode(data) {
38
+ const base64 = typeof data === 'string' ? Buffer.from(data).toString('base64') : data.toString('base64');
39
+ return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
40
+ }
41
+ /**
42
+ * Base64URL decode a string
43
+ */
44
+ function base64UrlDecode(data) {
45
+ // Add padding if needed
46
+ const padding = 4 - (data.length % 4);
47
+ const padded = padding < 4 ? data + '='.repeat(padding) : data;
48
+ const base64 = padded.replace(/-/g, '+').replace(/_/g, '/');
49
+ return Buffer.from(base64, 'base64');
50
+ }
51
+ /**
52
+ * Create JWT token using RS256
53
+ */
54
+ function createJWT(payload, privateKey) {
55
+ // Header
56
+ const header = {
57
+ alg: 'RS256',
58
+ typ: 'JWT',
59
+ };
60
+ // Encode header and payload
61
+ const encodedHeader = base64UrlEncode(JSON.stringify(header));
62
+ const encodedPayload = base64UrlEncode(JSON.stringify(payload));
63
+ // Create signature input
64
+ const signatureInput = `${encodedHeader}.${encodedPayload}`;
65
+ // Sign using RS256
66
+ const sign = createSign('RSA-SHA256');
67
+ sign.update(signatureInput);
68
+ const signature = sign.sign(privateKey);
69
+ // Encode signature
70
+ const encodedSignature = base64UrlEncode(signature);
71
+ return `${signatureInput}.${encodedSignature}`;
72
+ }
73
+ /**
74
+ * Verify JWT token using RS256
75
+ */
76
+ function verifyJWT(token, publicKey) {
77
+ const parts = token.split('.');
78
+ if (parts.length !== 3) {
79
+ return { valid: false, error: 'Invalid token format' };
80
+ }
81
+ const [encodedHeader, encodedPayload, encodedSignature] = parts;
82
+ try {
83
+ // Decode and verify header
84
+ const header = JSON.parse(base64UrlDecode(encodedHeader).toString());
85
+ if (header.alg !== 'RS256') {
86
+ return { valid: false, error: 'Invalid algorithm' };
87
+ }
88
+ // Verify signature
89
+ const signatureInput = `${encodedHeader}.${encodedPayload}`;
90
+ const signature = base64UrlDecode(encodedSignature);
91
+ const verify = createVerify('RSA-SHA256');
92
+ verify.update(signatureInput);
93
+ const isValid = verify.verify(publicKey, signature);
94
+ if (!isValid) {
95
+ return { valid: false, error: 'Invalid signature' };
96
+ }
97
+ // Decode payload
98
+ const payload = JSON.parse(base64UrlDecode(encodedPayload).toString());
99
+ return { valid: true, payload };
100
+ }
101
+ catch (error) {
102
+ return { valid: false, error: error instanceof Error ? error.message : 'Token verification failed' };
103
+ }
104
+ }
105
+ /**
106
+ * Token Service Implementation
107
+ */
108
+ class TokenServiceImpl {
109
+ config;
110
+ expirySeconds;
111
+ constructor(config) {
112
+ this.config = config;
113
+ this.expirySeconds = parseDuration(config.accessTokenExpiry);
114
+ }
115
+ async generateAccessToken(options) {
116
+ const now = Math.floor(Date.now() / 1000);
117
+ const exp = now + this.expirySeconds;
118
+ const claims = {
119
+ iss: this.config.issuer,
120
+ sub: options.userId,
121
+ aud: options.audience,
122
+ exp,
123
+ iat: now,
124
+ jti: randomUUID(),
125
+ client_id: options.clientId,
126
+ scope: options.scope,
127
+ };
128
+ const accessToken = createJWT(claims, this.config.privateKey);
129
+ return {
130
+ access_token: accessToken,
131
+ token_type: 'Bearer',
132
+ expires_in: this.expirySeconds,
133
+ scope: options.scope,
134
+ };
135
+ }
136
+ async verifyAccessToken(token, expectedAudience) {
137
+ const result = verifyJWT(token, this.config.publicKey);
138
+ if (!result.valid) {
139
+ return { valid: false, error: result.error };
140
+ }
141
+ const payload = result.payload;
142
+ // Verify issuer
143
+ if (payload.iss !== this.config.issuer) {
144
+ return { valid: false, error: 'Invalid issuer' };
145
+ }
146
+ // Verify expiration
147
+ const now = Math.floor(Date.now() / 1000);
148
+ if (payload.exp < now) {
149
+ return { valid: false, error: 'Token expired' };
150
+ }
151
+ // Verify audience if specified
152
+ if (expectedAudience && payload.aud !== expectedAudience) {
153
+ return { valid: false, error: 'Invalid audience' };
154
+ }
155
+ return { valid: true, claims: payload };
156
+ }
157
+ extractTokenFromHeader(header) {
158
+ if (!header) {
159
+ return null;
160
+ }
161
+ const parts = header.split(' ');
162
+ if (parts.length !== 2) {
163
+ return null;
164
+ }
165
+ if (parts[0].toLowerCase() !== 'bearer') {
166
+ return null;
167
+ }
168
+ const token = parts[1];
169
+ if (!token || token.trim() === '') {
170
+ return null;
171
+ }
172
+ return token;
173
+ }
174
+ }
175
+ /**
176
+ * Create a Token Service instance
177
+ */
178
+ export function createTokenService(config) {
179
+ return new TokenServiceImpl(config);
180
+ }
181
+ /**
182
+ * Generate RSA key pair for JWT signing
183
+ * Requirement: RS256 signing
184
+ */
185
+ export async function generateKeyPair() {
186
+ const { privateKey, publicKey } = generateKeyPairSync('rsa', {
187
+ modulusLength: 2048,
188
+ publicKeyEncoding: {
189
+ type: 'spki',
190
+ format: 'pem',
191
+ },
192
+ privateKeyEncoding: {
193
+ type: 'pkcs8',
194
+ format: 'pem',
195
+ },
196
+ });
197
+ return { privateKey, publicKey };
198
+ }
199
+ //# sourceMappingURL=token-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-service.js","sourceRoot":"","sources":["../../src/oauth/token-service.ts"],"names":[],"mappings":"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"}