integrate-sdk 0.3.7 → 0.3.8

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 (40) hide show
  1. package/dist/index.js +40 -0
  2. package/dist/server.js +15 -0
  3. package/dist/src/adapters/nextjs-oauth-redirect.d.ts +34 -0
  4. package/dist/src/adapters/nextjs-oauth-redirect.d.ts.map +1 -0
  5. package/dist/src/index.d.ts +3 -1
  6. package/dist/src/index.d.ts.map +1 -1
  7. package/dist/src/oauth/types.d.ts +0 -9
  8. package/dist/src/oauth/types.d.ts.map +1 -1
  9. package/dist/src/oauth/window-manager.d.ts +1 -1
  10. package/dist/src/oauth/window-manager.d.ts.map +1 -1
  11. package/package.json +3 -15
  12. package/dist/src/adapters/nextjs-callback.d.ts +0 -44
  13. package/dist/src/adapters/nextjs-callback.d.ts.map +0 -1
  14. package/src/adapters/auto-routes.ts +0 -217
  15. package/src/adapters/base-handler.ts +0 -212
  16. package/src/adapters/nextjs-callback.tsx +0 -160
  17. package/src/adapters/nextjs.ts +0 -318
  18. package/src/adapters/tanstack-start.ts +0 -264
  19. package/src/client.ts +0 -952
  20. package/src/config/types.ts +0 -180
  21. package/src/errors.ts +0 -207
  22. package/src/index.ts +0 -110
  23. package/src/integrations/vercel-ai.ts +0 -104
  24. package/src/oauth/manager.ts +0 -307
  25. package/src/oauth/pkce.ts +0 -127
  26. package/src/oauth/types.ts +0 -101
  27. package/src/oauth/window-manager.ts +0 -322
  28. package/src/plugins/generic.ts +0 -119
  29. package/src/plugins/github-client.ts +0 -345
  30. package/src/plugins/github.ts +0 -122
  31. package/src/plugins/gmail-client.ts +0 -114
  32. package/src/plugins/gmail.ts +0 -108
  33. package/src/plugins/server-client.ts +0 -20
  34. package/src/plugins/types.ts +0 -89
  35. package/src/protocol/jsonrpc.ts +0 -88
  36. package/src/protocol/messages.ts +0 -145
  37. package/src/server.ts +0 -117
  38. package/src/transport/http-session.ts +0 -322
  39. package/src/transport/http-stream.ts +0 -331
  40. package/src/utils/naming.ts +0 -52
@@ -1,307 +0,0 @@
1
- /**
2
- * OAuth Manager
3
- * Orchestrates OAuth 2.0 Authorization Code Flow with PKCE
4
- */
5
-
6
- import type { OAuthConfig } from "../plugins/types.js";
7
- import type {
8
- OAuthFlowConfig,
9
- PendingAuth,
10
- AuthStatus,
11
- AuthorizationUrlResponse,
12
- OAuthCallbackResponse,
13
- } from "./types.js";
14
- import { generateCodeVerifier, generateCodeChallenge, generateState } from "./pkce.js";
15
- import { OAuthWindowManager } from "./window-manager.js";
16
-
17
- /**
18
- * OAuth Manager
19
- * Handles OAuth authorization flows and token management
20
- */
21
- export class OAuthManager {
22
- private pendingAuths: Map<string, PendingAuth> = new Map();
23
- private sessionToken?: string;
24
- private windowManager: OAuthWindowManager;
25
- private flowConfig: OAuthFlowConfig;
26
- private oauthApiBase: string;
27
-
28
- constructor(
29
- oauthApiBase: string,
30
- flowConfig?: Partial<OAuthFlowConfig>
31
- ) {
32
- this.oauthApiBase = oauthApiBase;
33
- this.windowManager = new OAuthWindowManager();
34
- this.flowConfig = {
35
- mode: flowConfig?.mode || 'redirect',
36
- popupOptions: flowConfig?.popupOptions,
37
- onAuthCallback: flowConfig?.onAuthCallback,
38
- };
39
- }
40
-
41
- /**
42
- * Initiate OAuth authorization flow
43
- *
44
- * @param provider - OAuth provider (github, gmail, etc.)
45
- * @param config - OAuth configuration
46
- * @returns Promise that resolves when authorization is complete
47
- *
48
- * @example
49
- * ```typescript
50
- * await oauthManager.initiateFlow('github', {
51
- * provider: 'github',
52
- * clientId: 'abc123',
53
- * clientSecret: 'secret',
54
- * scopes: ['repo', 'user']
55
- * });
56
- * ```
57
- */
58
- async initiateFlow(provider: string, config: OAuthConfig): Promise<void> {
59
- // 1. Generate PKCE parameters
60
- const codeVerifier = generateCodeVerifier();
61
- const codeChallenge = await generateCodeChallenge(codeVerifier);
62
- const state = generateState();
63
-
64
- // 2. Store pending auth
65
- const pendingAuth: PendingAuth = {
66
- provider,
67
- state,
68
- codeVerifier,
69
- codeChallenge,
70
- scopes: config.scopes,
71
- redirectUri: config.redirectUri,
72
- initiatedAt: Date.now(),
73
- };
74
- this.pendingAuths.set(state, pendingAuth);
75
-
76
- // 3. Request authorization URL from user's API route
77
- const authUrl = await this.getAuthorizationUrl(provider, config.scopes, state, codeChallenge, config.redirectUri);
78
-
79
- // 4. Open authorization URL (popup or redirect)
80
- if (this.flowConfig.mode === 'popup') {
81
- this.windowManager.openPopup(authUrl, this.flowConfig.popupOptions);
82
-
83
- // Wait for callback from popup
84
- try {
85
- const callbackParams = await this.windowManager.listenForCallback('popup');
86
- await this.handleCallback(callbackParams.code, callbackParams.state);
87
- } catch (error) {
88
- // Clean up pending auth on error
89
- this.pendingAuths.delete(state);
90
- throw error;
91
- }
92
- } else {
93
- // For redirect mode, just redirect - callback will be handled separately
94
- this.windowManager.openRedirect(authUrl);
95
- }
96
- }
97
-
98
- /**
99
- * Handle OAuth callback
100
- * Call this after user authorizes (from your callback page)
101
- *
102
- * @param code - Authorization code from OAuth provider
103
- * @param state - State parameter for verification
104
- * @returns Session token for authenticated requests
105
- *
106
- * @example
107
- * ```typescript
108
- * // In your callback route
109
- * const sessionToken = await oauthManager.handleCallback(code, state);
110
- * ```
111
- */
112
- async handleCallback(code: string, state: string): Promise<string> {
113
- // 1. Verify state and get pending auth
114
- const pendingAuth = this.pendingAuths.get(state);
115
-
116
- if (!pendingAuth) {
117
- throw new Error('Invalid state parameter: no matching OAuth flow found');
118
- }
119
-
120
- // Check if auth is not too old (5 minutes)
121
- const fiveMinutes = 5 * 60 * 1000;
122
- if (Date.now() - pendingAuth.initiatedAt > fiveMinutes) {
123
- this.pendingAuths.delete(state);
124
- throw new Error('OAuth flow expired: please try again');
125
- }
126
-
127
- // Call custom callback handler if provided
128
- if (this.flowConfig.onAuthCallback) {
129
- try {
130
- await this.flowConfig.onAuthCallback(pendingAuth.provider, code, state);
131
- } catch (error) {
132
- console.error('Custom OAuth callback handler failed:', error);
133
- }
134
- }
135
-
136
- // 2. Send to user's API route for token exchange
137
- try {
138
- const response = await this.exchangeCodeForToken(
139
- pendingAuth.provider,
140
- code,
141
- pendingAuth.codeVerifier,
142
- state
143
- );
144
-
145
- // 3. Store session token
146
- this.sessionToken = response.sessionToken;
147
-
148
- // 4. Clean up pending auth
149
- this.pendingAuths.delete(state);
150
-
151
- return response.sessionToken;
152
- } catch (error) {
153
- this.pendingAuths.delete(state);
154
- throw error;
155
- }
156
- }
157
-
158
- /**
159
- * Check authorization status for a provider
160
- *
161
- * @param provider - OAuth provider to check
162
- * @returns Authorization status
163
- *
164
- * @example
165
- * ```typescript
166
- * const status = await oauthManager.checkAuthStatus('github');
167
- * if (status.authorized) {
168
- * console.log('GitHub is authorized');
169
- * }
170
- * ```
171
- */
172
- async checkAuthStatus(provider: string): Promise<AuthStatus> {
173
- if (!this.sessionToken) {
174
- return {
175
- authorized: false,
176
- provider,
177
- };
178
- }
179
-
180
- try {
181
- const url = `${this.oauthApiBase}/status?provider=${encodeURIComponent(provider)}`;
182
-
183
- const response = await fetch(url, {
184
- method: 'GET',
185
- headers: {
186
- 'X-Session-Token': this.sessionToken,
187
- },
188
- });
189
-
190
- if (!response.ok) {
191
- return {
192
- authorized: false,
193
- provider,
194
- };
195
- }
196
-
197
- const status = await response.json() as AuthStatus;
198
- return status;
199
- } catch (error) {
200
- console.error('Failed to check auth status:', error);
201
- return {
202
- authorized: false,
203
- provider,
204
- };
205
- }
206
- }
207
-
208
- /**
209
- * Get session token
210
- */
211
- getSessionToken(): string | undefined {
212
- return this.sessionToken;
213
- }
214
-
215
- /**
216
- * Set session token (for manual token management)
217
- */
218
- setSessionToken(token: string): void {
219
- this.sessionToken = token;
220
- }
221
-
222
- /**
223
- * Clear session token
224
- */
225
- clearSessionToken(): void {
226
- this.sessionToken = undefined;
227
- }
228
-
229
- /**
230
- * Request authorization URL from user's API route
231
- * The API route will add OAuth secrets and forward to MCP server
232
- */
233
- private async getAuthorizationUrl(
234
- provider: string,
235
- scopes: string[],
236
- state: string,
237
- codeChallenge: string,
238
- redirectUri?: string
239
- ): Promise<string> {
240
- const url = `${this.oauthApiBase}/authorize`;
241
-
242
- const response = await fetch(url, {
243
- method: 'POST',
244
- headers: {
245
- 'Content-Type': 'application/json',
246
- },
247
- body: JSON.stringify({
248
- provider,
249
- scopes,
250
- state,
251
- codeChallenge,
252
- codeChallengeMethod: 'S256',
253
- redirectUri,
254
- }),
255
- });
256
-
257
- if (!response.ok) {
258
- const error = await response.text();
259
- throw new Error(`Failed to get authorization URL: ${error}`);
260
- }
261
-
262
- const data = await response.json() as AuthorizationUrlResponse;
263
- return data.authorizationUrl;
264
- }
265
-
266
- /**
267
- * Exchange authorization code for session token via user's API route
268
- * The API route will forward to MCP server
269
- */
270
- private async exchangeCodeForToken(
271
- provider: string,
272
- code: string,
273
- codeVerifier: string,
274
- state: string
275
- ): Promise<OAuthCallbackResponse> {
276
- const url = `${this.oauthApiBase}/callback`;
277
-
278
- const response = await fetch(url, {
279
- method: 'POST',
280
- headers: {
281
- 'Content-Type': 'application/json',
282
- },
283
- body: JSON.stringify({
284
- provider,
285
- code,
286
- codeVerifier,
287
- state,
288
- }),
289
- });
290
-
291
- if (!response.ok) {
292
- const error = await response.text();
293
- throw new Error(`Failed to exchange code for token: ${error}`);
294
- }
295
-
296
- const data = await response.json() as OAuthCallbackResponse;
297
- return data;
298
- }
299
-
300
- /**
301
- * Close any open OAuth windows
302
- */
303
- close(): void {
304
- this.windowManager.close();
305
- }
306
- }
307
-
package/src/oauth/pkce.ts DELETED
@@ -1,127 +0,0 @@
1
- /**
2
- * PKCE Utilities
3
- * Proof Key for Code Exchange (RFC 7636) implementation
4
- *
5
- * PKCE enhances OAuth 2.0 security by preventing authorization code interception attacks.
6
- * It's especially important for public clients (browser/mobile apps).
7
- */
8
-
9
- /**
10
- * Generate a cryptographically secure random code verifier
11
- * Must be 43-128 characters long, using [A-Z] [a-z] [0-9] - . _ ~
12
- *
13
- * @returns A random code verifier string
14
- *
15
- * @example
16
- * ```typescript
17
- * const verifier = generateCodeVerifier();
18
- * // Returns: "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"
19
- * ```
20
- */
21
- export function generateCodeVerifier(): string {
22
- // Generate 32 random bytes (will be 43 characters when base64url encoded)
23
- const array = new Uint8Array(32);
24
-
25
- if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
26
- // Browser/modern environment
27
- crypto.getRandomValues(array);
28
- } else if (typeof globalThis !== 'undefined' && (globalThis as any).crypto) {
29
- // Node.js 19+
30
- (globalThis as any).crypto.getRandomValues(array);
31
- } else {
32
- // Fallback for older Node.js
33
- throw new Error('crypto.getRandomValues is not available. Please use Node.js 19+ or a modern browser.');
34
- }
35
-
36
- return base64UrlEncode(array);
37
- }
38
-
39
- /**
40
- * Generate code challenge from verifier using SHA-256
41
- *
42
- * @param verifier - The code verifier to hash
43
- * @returns A Promise resolving to the base64url-encoded SHA-256 hash
44
- *
45
- * @example
46
- * ```typescript
47
- * const verifier = generateCodeVerifier();
48
- * const challenge = await generateCodeChallenge(verifier);
49
- * // Returns: "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM"
50
- * ```
51
- */
52
- export async function generateCodeChallenge(verifier: string): Promise<string> {
53
- // Convert verifier to Uint8Array
54
- const encoder = new TextEncoder();
55
- const data = encoder.encode(verifier);
56
-
57
- // Hash with SHA-256
58
- let hashBuffer: ArrayBuffer;
59
-
60
- if (typeof crypto !== 'undefined' && crypto.subtle) {
61
- // Browser/modern environment
62
- hashBuffer = await crypto.subtle.digest('SHA-256', data);
63
- } else if (typeof globalThis !== 'undefined' && (globalThis as any).crypto?.subtle) {
64
- // Node.js 19+
65
- hashBuffer = await (globalThis as any).crypto.subtle.digest('SHA-256', data);
66
- } else {
67
- // Fallback for older Node.js
68
- throw new Error('crypto.subtle.digest is not available. Please use Node.js 19+ or a modern browser.');
69
- }
70
-
71
- // Convert to base64url
72
- return base64UrlEncode(new Uint8Array(hashBuffer));
73
- }
74
-
75
- /**
76
- * Generate a random state parameter for CSRF protection
77
- *
78
- * @returns A random state string
79
- *
80
- * @example
81
- * ```typescript
82
- * const state = generateState();
83
- * // Returns: "xyzABC123"
84
- * ```
85
- */
86
- export function generateState(): string {
87
- // Generate 16 random bytes (will be 22 characters when base64url encoded)
88
- const array = new Uint8Array(16);
89
-
90
- if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
91
- crypto.getRandomValues(array);
92
- } else if (typeof globalThis !== 'undefined' && (globalThis as any).crypto) {
93
- (globalThis as any).crypto.getRandomValues(array);
94
- } else {
95
- throw new Error('crypto.getRandomValues is not available. Please use Node.js 19+ or a modern browser.');
96
- }
97
-
98
- return base64UrlEncode(array);
99
- }
100
-
101
- /**
102
- * Base64url encode a Uint8Array
103
- * Base64url encoding uses URL-safe characters (no +, /, =)
104
- *
105
- * @param array - The byte array to encode
106
- * @returns Base64url-encoded string
107
- */
108
- function base64UrlEncode(array: Uint8Array): string {
109
- // Convert to base64
110
- let base64 = '';
111
-
112
- if (typeof Buffer !== 'undefined') {
113
- // Node.js
114
- base64 = Buffer.from(array).toString('base64');
115
- } else {
116
- // Browser
117
- const binary = String.fromCharCode(...array);
118
- base64 = btoa(binary);
119
- }
120
-
121
- // Convert to base64url (replace +/= with -_)
122
- return base64
123
- .replace(/\+/g, '-')
124
- .replace(/\//g, '_')
125
- .replace(/=/g, '');
126
- }
127
-
@@ -1,101 +0,0 @@
1
- /**
2
- * OAuth Flow Types
3
- * Type definitions for OAuth 2.0 Authorization Code Flow with PKCE
4
- */
5
-
6
- /**
7
- * Popup window options for OAuth flow
8
- */
9
- export interface PopupOptions {
10
- /** Window width in pixels (default: 600) */
11
- width?: number;
12
- /** Window height in pixels (default: 700) */
13
- height?: number;
14
- }
15
-
16
- /**
17
- * OAuth flow configuration
18
- */
19
- export interface OAuthFlowConfig {
20
- /** How to display OAuth authorization */
21
- mode: 'popup' | 'redirect';
22
- /** Popup window dimensions (only for popup mode) */
23
- popupOptions?: PopupOptions;
24
- /** Custom callback handler for receiving auth code */
25
- onAuthCallback?: (provider: string, code: string, state: string) => Promise<void>;
26
- }
27
-
28
- /**
29
- * Authorization status for a provider
30
- */
31
- export interface AuthStatus {
32
- /** Whether the provider is authorized */
33
- authorized: boolean;
34
- /** The provider name */
35
- provider: string;
36
- /** Authorized scopes */
37
- scopes?: string[];
38
- /** Token expiration time */
39
- expiresAt?: string;
40
- }
41
-
42
- /**
43
- * Pending OAuth authorization
44
- * Tracks in-progress OAuth flows
45
- */
46
- export interface PendingAuth {
47
- /** OAuth provider (github, gmail, etc.) */
48
- provider: string;
49
- /** CSRF protection state */
50
- state: string;
51
- /** PKCE code verifier */
52
- codeVerifier: string;
53
- /** PKCE code challenge */
54
- codeChallenge: string;
55
- /** OAuth scopes being requested */
56
- scopes: string[];
57
- /** Redirect URI */
58
- redirectUri?: string;
59
- /** Timestamp when auth was initiated */
60
- initiatedAt: number;
61
- }
62
-
63
- /**
64
- * OAuth authorization URL response from server
65
- */
66
- export interface AuthorizationUrlResponse {
67
- /** The full authorization URL to redirect user to */
68
- authorizationUrl: string;
69
- }
70
-
71
- /**
72
- * OAuth callback response from server
73
- * Contains session token after successful authorization
74
- */
75
- export interface OAuthCallbackResponse {
76
- /** Session token for authenticated requests */
77
- sessionToken: string;
78
- /** Token expiration time */
79
- expiresAt?: string;
80
- }
81
-
82
- /**
83
- * Parameters for OAuth callback
84
- */
85
- export interface OAuthCallbackParams {
86
- /** Authorization code from OAuth provider */
87
- code: string;
88
- /** State parameter for CSRF protection */
89
- state: string;
90
- }
91
-
92
- /**
93
- * Configuration for OAuth callback route handler
94
- */
95
- export interface OAuthCallbackHandlerConfig {
96
- /** URL to redirect to after successful OAuth (default: '/') */
97
- redirectUrl?: string;
98
- /** URL to redirect to on OAuth error (default: '/auth-error') */
99
- errorRedirectUrl?: string;
100
- }
101
-