@flink-app/oauth-plugin 0.12.1-alpha.35 → 0.12.1-alpha.36

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.
@@ -1,4 +1,27 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
27
  };
@@ -8,6 +31,8 @@ const flink_1 = require("@flink-app/flink");
8
31
  const OAuthSessionRepo_1 = __importDefault(require("./repos/OAuthSessionRepo"));
9
32
  const OAuthConnectionRepo_1 = __importDefault(require("./repos/OAuthConnectionRepo"));
10
33
  const encryption_utils_1 = require("./utils/encryption-utils");
34
+ const InitiateOAuth = __importStar(require("./handlers/InitiateOAuth"));
35
+ const CallbackOAuth = __importStar(require("./handlers/CallbackOAuth"));
11
36
  /**
12
37
  * OAuth Plugin Factory Function
13
38
  *
@@ -139,10 +164,12 @@ function oauthPlugin(options) {
139
164
  const sessionTTL = options.sessionTTL || 600; // Default 10 minutes
140
165
  await db.collection(sessionsCollectionName).createIndex({ createdAt: 1 }, { expireAfterSeconds: sessionTTL });
141
166
  flink_1.log.info(`OAuth Plugin: Created TTL index on ${sessionsCollectionName} with ${sessionTTL}s expiration`);
142
- // Register handlers for each configured provider
143
- // Note: Handlers will be registered dynamically
144
- // This requires handlers to be imported, but we'll handle that in the handler files
145
- // For now, we'll skip handler registration and implement it when handlers are ready
167
+ // Register OAuth handlers
168
+ // Only register handlers if registerRoutes is enabled (default: true)
169
+ if (options.registerRoutes !== false) {
170
+ flinkApp.addHandler(InitiateOAuth);
171
+ flinkApp.addHandler(CallbackOAuth);
172
+ }
146
173
  flink_1.log.info(`OAuth Plugin initialized with providers: ${configuredProviders.join(", ")}`);
147
174
  }
148
175
  catch (error) {
@@ -108,4 +108,10 @@ export interface OAuthPluginOptions {
108
108
  * Recommended: Use a dedicated encryption key from environment variables
109
109
  */
110
110
  encryptionKey?: string;
111
+ /**
112
+ * Whether to register OAuth routes automatically
113
+ * If false, you must manually handle OAuth flow
114
+ * Default: true
115
+ */
116
+ registerRoutes?: boolean;
111
117
  }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * OAuth Callback Handler
3
+ *
4
+ * Handles the OAuth 2.0 callback from the provider by:
5
+ * 1. Validating the state parameter to prevent CSRF attacks
6
+ * 2. Exchanging the authorization code for an access token
7
+ * 3. Fetching the user profile from the provider
8
+ * 4. Calling the onAuthSuccess callback to create/link user and generate JWT token
9
+ * 5. Optionally storing the OAuth connection (if storeTokens enabled)
10
+ * 6. Returning the JWT token to the client (via JSON or redirect)
11
+ *
12
+ * Route: GET /oauth/:provider/callback?code=...&state=...&response_type=json
13
+ */
14
+ import { GetHandler, RouteProps } from "@flink-app/flink";
15
+ import CallbackRequest from "../schemas/CallbackRequest";
16
+ /**
17
+ * Path parameters for the handler
18
+ */
19
+ interface PathParams {
20
+ provider: string;
21
+ [key: string]: string;
22
+ }
23
+ /**
24
+ * Route configuration
25
+ * Note: This handler is registered programmatically by the plugin
26
+ * with dynamic provider parameter support
27
+ */
28
+ export declare const Route: RouteProps;
29
+ /**
30
+ * OAuth Callback Handler
31
+ *
32
+ * Completes the OAuth flow by exchanging the authorization code for tokens,
33
+ * fetching user profile, calling the app's onAuthSuccess callback to generate
34
+ * JWT token, and returning the token to the client.
35
+ */
36
+ declare const CallbackOAuth: GetHandler<any, any, PathParams, CallbackRequest>;
37
+ export default CallbackOAuth;
@@ -0,0 +1,200 @@
1
+ "use strict";
2
+ /**
3
+ * OAuth Callback Handler
4
+ *
5
+ * Handles the OAuth 2.0 callback from the provider by:
6
+ * 1. Validating the state parameter to prevent CSRF attacks
7
+ * 2. Exchanging the authorization code for an access token
8
+ * 3. Fetching the user profile from the provider
9
+ * 4. Calling the onAuthSuccess callback to create/link user and generate JWT token
10
+ * 5. Optionally storing the OAuth connection (if storeTokens enabled)
11
+ * 6. Returning the JWT token to the client (via JSON or redirect)
12
+ *
13
+ * Route: GET /oauth/:provider/callback?code=...&state=...&response_type=json
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.Route = void 0;
17
+ const flink_1 = require("@flink-app/flink");
18
+ const state_utils_1 = require("../utils/state-utils");
19
+ const ProviderRegistry_1 = require("../providers/ProviderRegistry");
20
+ const token_response_utils_1 = require("../utils/token-response-utils");
21
+ const encryption_utils_1 = require("../utils/encryption-utils");
22
+ const error_utils_1 = require("../utils/error-utils");
23
+ /**
24
+ * Route configuration
25
+ * Note: This handler is registered programmatically by the plugin
26
+ * with dynamic provider parameter support
27
+ */
28
+ exports.Route = {
29
+ path: "/oauth/:provider/callback",
30
+ };
31
+ /**
32
+ * OAuth Callback Handler
33
+ *
34
+ * Completes the OAuth flow by exchanging the authorization code for tokens,
35
+ * fetching user profile, calling the app's onAuthSuccess callback to generate
36
+ * JWT token, and returning the token to the client.
37
+ */
38
+ const CallbackOAuth = async ({ ctx, req }) => {
39
+ const { provider } = req.params;
40
+ const { code, state, error: oauthError, response_type } = req.query;
41
+ try {
42
+ // Validate provider and response_type
43
+ (0, error_utils_1.validateProvider)(provider);
44
+ (0, error_utils_1.validateResponseType)(response_type);
45
+ // Check for OAuth provider errors (e.g., user denied access)
46
+ if (oauthError) {
47
+ const error = (0, error_utils_1.handleProviderError)({ error: oauthError });
48
+ // Call onAuthError callback if provided
49
+ const { options } = ctx.plugins.oauth;
50
+ if (options.onAuthError) {
51
+ const errorResult = await options.onAuthError({
52
+ error,
53
+ provider: provider,
54
+ });
55
+ if (errorResult.redirectUrl) {
56
+ return {
57
+ status: 302,
58
+ headers: { Location: errorResult.redirectUrl },
59
+ data: {},
60
+ };
61
+ }
62
+ }
63
+ return (0, flink_1.badRequest)(error.message);
64
+ }
65
+ // Validate required parameters
66
+ if (!code || !state) {
67
+ throw (0, error_utils_1.createOAuthError)(error_utils_1.OAuthErrorCodes.MISSING_CODE, "Missing authorization code or state parameter", { hasCode: !!code, hasState: !!state });
68
+ }
69
+ // Find OAuth session by state
70
+ const session = await ctx.repos.oauthSessionRepo.getOne({ state });
71
+ if (!session) {
72
+ throw (0, error_utils_1.createOAuthError)(error_utils_1.OAuthErrorCodes.SESSION_EXPIRED, "OAuth session not found or expired. Please try logging in again.", { state });
73
+ }
74
+ // Validate state parameter (CSRF protection)
75
+ if (!(0, state_utils_1.validateState)(state, session.state)) {
76
+ throw (0, error_utils_1.createOAuthError)(error_utils_1.OAuthErrorCodes.INVALID_STATE, "Invalid state parameter. Possible CSRF attack detected.", {
77
+ providedState: state.substring(0, 10) + "...",
78
+ });
79
+ }
80
+ // Delete session immediately after validation (one-time use)
81
+ await ctx.repos.oauthSessionRepo.deleteBySessionId(session.sessionId);
82
+ // Get plugin options and provider config
83
+ const { options } = ctx.plugins.oauth;
84
+ const providerConfig = options.providers[provider];
85
+ if (!providerConfig) {
86
+ throw (0, error_utils_1.createOAuthError)(error_utils_1.OAuthErrorCodes.INVALID_PROVIDER, `Provider "${provider}" is not configured`, { provider });
87
+ }
88
+ // Exchange authorization code for access token
89
+ const oauthProvider = (0, ProviderRegistry_1.getProvider)(provider, providerConfig);
90
+ const tokens = await oauthProvider.exchangeCodeForToken({
91
+ code,
92
+ redirectUri: providerConfig.callbackUrl,
93
+ });
94
+ // Fetch user profile from provider
95
+ const profile = await oauthProvider.getUserProfile(tokens.accessToken);
96
+ // Call onAuthSuccess callback to create/link user and generate JWT token
97
+ const authSuccessParams = {
98
+ profile,
99
+ provider: provider,
100
+ ...(options.storeTokens ? { tokens } : {}),
101
+ };
102
+ let authResult;
103
+ try {
104
+ authResult = await options.onAuthSuccess(authSuccessParams, ctx);
105
+ }
106
+ catch (error) {
107
+ // Handle JWT generation or user creation errors
108
+ flink_1.log.error("OAuth onAuthSuccess callback failed:", error);
109
+ const oauthError = (0, error_utils_1.createOAuthError)(error_utils_1.OAuthErrorCodes.JWT_GENERATION_FAILED, "Failed to complete authentication. Please try again.", {
110
+ originalError: error.message,
111
+ });
112
+ // Call onAuthError callback if provided
113
+ if (options.onAuthError) {
114
+ const errorResult = await options.onAuthError({
115
+ error: oauthError,
116
+ provider: provider,
117
+ });
118
+ if (errorResult.redirectUrl) {
119
+ return {
120
+ status: 302,
121
+ headers: { Location: errorResult.redirectUrl },
122
+ data: {},
123
+ };
124
+ }
125
+ }
126
+ return (0, flink_1.internalServerError)("Authentication failed. Please try again.");
127
+ }
128
+ // Extract user and JWT token from callback result
129
+ const { user, token, redirectUrl } = authResult;
130
+ if (!token) {
131
+ throw (0, error_utils_1.createOAuthError)(error_utils_1.OAuthErrorCodes.JWT_GENERATION_FAILED, "No authentication token returned from callback", { hasUser: !!user });
132
+ }
133
+ // Store OAuth connection if token storage is enabled
134
+ if (options.storeTokens && user && user._id) {
135
+ const encryptionSecret = providerConfig.clientSecret;
136
+ // Encrypt tokens before storing
137
+ const encryptedAccessToken = (0, encryption_utils_1.encryptToken)(tokens.accessToken, encryptionSecret);
138
+ const encryptedRefreshToken = tokens.refreshToken ? (0, encryption_utils_1.encryptToken)(tokens.refreshToken, encryptionSecret) : undefined;
139
+ // Calculate token expiration
140
+ const expiresAt = tokens.expiresIn ? new Date(Date.now() + tokens.expiresIn * 1000) : undefined;
141
+ // Create or update OAuth connection
142
+ const existingConnection = await ctx.repos.oauthConnectionRepo.findByUserAndProvider(user._id, provider);
143
+ if (existingConnection) {
144
+ await ctx.repos.oauthConnectionRepo.updateOne(existingConnection._id, {
145
+ accessToken: encryptedAccessToken,
146
+ refreshToken: encryptedRefreshToken,
147
+ scope: tokens.scope || "",
148
+ expiresAt,
149
+ updatedAt: new Date(),
150
+ });
151
+ }
152
+ else {
153
+ await ctx.repos.oauthConnectionRepo.create({
154
+ userId: user._id,
155
+ provider: provider,
156
+ providerId: profile.id,
157
+ accessToken: encryptedAccessToken,
158
+ refreshToken: encryptedRefreshToken,
159
+ scope: tokens.scope || "",
160
+ expiresAt,
161
+ createdAt: new Date(),
162
+ updatedAt: new Date(),
163
+ });
164
+ }
165
+ }
166
+ // Return JWT token in requested format
167
+ return (0, token_response_utils_1.formatTokenResponse)(token, user, redirectUrl || session.redirectUri, response_type);
168
+ }
169
+ catch (error) {
170
+ flink_1.log.error("OAuth callback error:", error);
171
+ // Handle OAuth-specific errors
172
+ if (error.code && Object.values(error_utils_1.OAuthErrorCodes).includes(error.code)) {
173
+ // Call onAuthError callback if provided
174
+ const { options } = ctx.plugins.oauth;
175
+ if (options.onAuthError) {
176
+ try {
177
+ const errorResult = await options.onAuthError({
178
+ error,
179
+ provider: provider,
180
+ });
181
+ if (errorResult.redirectUrl) {
182
+ return {
183
+ status: 302,
184
+ headers: { Location: errorResult.redirectUrl },
185
+ data: {},
186
+ };
187
+ }
188
+ }
189
+ catch (callbackError) {
190
+ flink_1.log.error("onAuthError callback failed:", callbackError);
191
+ }
192
+ }
193
+ return (0, flink_1.badRequest)(error.message);
194
+ }
195
+ // Handle provider errors
196
+ const mappedError = (0, error_utils_1.handleProviderError)(error);
197
+ return (0, flink_1.internalServerError)(mappedError.message);
198
+ }
199
+ };
200
+ exports.default = CallbackOAuth;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * OAuth Initiate Handler
3
+ *
4
+ * Initiates the OAuth 2.0 authorization code flow by:
5
+ * 1. Validating the provider is supported and configured
6
+ * 2. Generating a cryptographically secure state parameter for CSRF protection
7
+ * 3. Creating an OAuth session to track the flow
8
+ * 4. Building the provider's authorization URL
9
+ * 5. Redirecting the user to the provider for authorization
10
+ *
11
+ * Route: GET /oauth/:provider/initiate?redirectUri={optional_redirect_url}
12
+ */
13
+ import { GetHandler, RouteProps } from "@flink-app/flink";
14
+ import InitiateRequest from "../schemas/InitiateRequest";
15
+ /**
16
+ * Path parameters for the handler
17
+ */
18
+ interface PathParams {
19
+ provider: string;
20
+ [key: string]: string;
21
+ }
22
+ /**
23
+ * Route configuration
24
+ * Note: This handler is registered programmatically by the plugin
25
+ * with dynamic provider parameter support
26
+ */
27
+ export declare const Route: RouteProps;
28
+ /**
29
+ * OAuth Initiate Handler
30
+ *
31
+ * Starts the OAuth flow by generating state, creating a session,
32
+ * and redirecting to the OAuth provider's authorization URL.
33
+ */
34
+ declare const InitiateOAuth: GetHandler<any, any, PathParams, InitiateRequest>;
35
+ export default InitiateOAuth;
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ /**
3
+ * OAuth Initiate Handler
4
+ *
5
+ * Initiates the OAuth 2.0 authorization code flow by:
6
+ * 1. Validating the provider is supported and configured
7
+ * 2. Generating a cryptographically secure state parameter for CSRF protection
8
+ * 3. Creating an OAuth session to track the flow
9
+ * 4. Building the provider's authorization URL
10
+ * 5. Redirecting the user to the provider for authorization
11
+ *
12
+ * Route: GET /oauth/:provider/initiate?redirectUri={optional_redirect_url}
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.Route = void 0;
16
+ const flink_1 = require("@flink-app/flink");
17
+ const state_utils_1 = require("../utils/state-utils");
18
+ const ProviderRegistry_1 = require("../providers/ProviderRegistry");
19
+ const error_utils_1 = require("../utils/error-utils");
20
+ /**
21
+ * Route configuration
22
+ * Note: This handler is registered programmatically by the plugin
23
+ * with dynamic provider parameter support
24
+ */
25
+ exports.Route = {
26
+ path: "/oauth/:provider/initiate",
27
+ };
28
+ /**
29
+ * OAuth Initiate Handler
30
+ *
31
+ * Starts the OAuth flow by generating state, creating a session,
32
+ * and redirecting to the OAuth provider's authorization URL.
33
+ */
34
+ const InitiateOAuth = async ({ ctx, req }) => {
35
+ const { provider } = req.params;
36
+ const { redirectUri } = req.query;
37
+ try {
38
+ // Validate provider is supported
39
+ (0, error_utils_1.validateProvider)(provider);
40
+ // Get plugin options and provider config
41
+ const { options } = ctx.plugins.oauth;
42
+ const providerConfig = options.providers[provider];
43
+ if (!providerConfig) {
44
+ throw (0, error_utils_1.createOAuthError)(error_utils_1.OAuthErrorCodes.INVALID_PROVIDER, `Provider "${provider}" is not configured`, { provider });
45
+ }
46
+ // Generate cryptographically secure state and session ID
47
+ const state = (0, state_utils_1.generateState)();
48
+ const sessionId = (0, state_utils_1.generateSessionId)();
49
+ // Store session for state validation in callback
50
+ await ctx.repos.oauthSessionRepo.create({
51
+ sessionId,
52
+ state,
53
+ provider: provider,
54
+ redirectUri: redirectUri || providerConfig.callbackUrl,
55
+ createdAt: new Date(),
56
+ });
57
+ // Get provider instance and build authorization URL
58
+ const oauthProvider = (0, ProviderRegistry_1.getProvider)(provider, providerConfig);
59
+ const authorizationUrl = oauthProvider.getAuthorizationUrl({
60
+ state,
61
+ redirectUri: providerConfig.callbackUrl,
62
+ scope: providerConfig.scope || [],
63
+ });
64
+ // Redirect user to provider's authorization page
65
+ return {
66
+ status: 302,
67
+ headers: {
68
+ Location: authorizationUrl,
69
+ },
70
+ data: {},
71
+ };
72
+ }
73
+ catch (error) {
74
+ // Handle validation errors
75
+ if (error.code && Object.values(error_utils_1.OAuthErrorCodes).includes(error.code)) {
76
+ return (0, flink_1.badRequest)(error.message);
77
+ }
78
+ // Handle unexpected errors
79
+ return (0, flink_1.internalServerError)(error.message || "Failed to initiate OAuth flow");
80
+ }
81
+ };
82
+ exports.default = InitiateOAuth;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Query parameters for OAuth callback request
3
+ */
4
+ export default interface CallbackRequest {
5
+ /**
6
+ * Authorization code from OAuth provider
7
+ */
8
+ code: string;
9
+ /**
10
+ * CSRF protection state parameter
11
+ */
12
+ state: string;
13
+ /**
14
+ * Optional error from OAuth provider
15
+ * Common values: access_denied, invalid_request, unauthorized_client, etc.
16
+ */
17
+ error?: string;
18
+ /**
19
+ * Human-readable error description (OAuth 2.0 standard)
20
+ */
21
+ error_description?: string;
22
+ /**
23
+ * URI with error information (OAuth 2.0 standard)
24
+ */
25
+ error_uri?: string;
26
+ /**
27
+ * Response type - 'json' returns JSON instead of redirect
28
+ */
29
+ response_type?: "json";
30
+ /**
31
+ * Granted scopes (provider-specific)
32
+ * May be sent by GitHub, Google, and other providers
33
+ */
34
+ scope?: string;
35
+ /**
36
+ * Google-specific: Index of the account selected by the user
37
+ */
38
+ authuser?: string;
39
+ /**
40
+ * Google-specific: Indicates which prompt was shown to the user
41
+ * Values: none, consent, select_account
42
+ */
43
+ prompt?: string;
44
+ /**
45
+ * Google-specific: Hosted domain of the user
46
+ */
47
+ hd?: string;
48
+ /**
49
+ * Session state or other provider-specific parameters
50
+ */
51
+ session_state?: string;
52
+ [key: string]: string | undefined;
53
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Query parameters for OAuth initiate request
3
+ */
4
+ export default interface InitiateRequest {
5
+ /**
6
+ * Optional redirect URI to return to after OAuth flow completes
7
+ */
8
+ redirectUri?: string;
9
+ [key: string]: string | undefined;
10
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Formats the OAuth callback response with JWT token.
3
+ * Supports multiple response formats:
4
+ * - JSON response with user and token
5
+ * - URL fragment redirect with token
6
+ * - Query parameter redirect with token
7
+ *
8
+ * @param token - JWT token to return
9
+ * @param user - User object to return
10
+ * @param redirectUrl - Optional redirect URL
11
+ * @param responseType - Response format ('json' or undefined for redirect)
12
+ * @returns Response object for Flink handler
13
+ */
14
+ export declare function formatTokenResponse(token: string, user: any, redirectUrl?: string, responseType?: string): any;
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatTokenResponse = void 0;
4
+ /**
5
+ * Formats the OAuth callback response with JWT token.
6
+ * Supports multiple response formats:
7
+ * - JSON response with user and token
8
+ * - URL fragment redirect with token
9
+ * - Query parameter redirect with token
10
+ *
11
+ * @param token - JWT token to return
12
+ * @param user - User object to return
13
+ * @param redirectUrl - Optional redirect URL
14
+ * @param responseType - Response format ('json' or undefined for redirect)
15
+ * @returns Response object for Flink handler
16
+ */
17
+ function formatTokenResponse(token, user, redirectUrl, responseType) {
18
+ // JSON response format
19
+ if (responseType === "json") {
20
+ return {
21
+ status: 200,
22
+ data: {
23
+ user,
24
+ token,
25
+ },
26
+ };
27
+ }
28
+ // Redirect format
29
+ if (redirectUrl) {
30
+ // Use URL fragment for better security (token not sent to server)
31
+ const separator = redirectUrl.includes("#") ? "&" : "#";
32
+ const fullRedirectUrl = `${redirectUrl}${separator}token=${encodeURIComponent(token)}`;
33
+ return {
34
+ status: 302,
35
+ headers: {
36
+ Location: fullRedirectUrl,
37
+ },
38
+ data: {},
39
+ };
40
+ }
41
+ // Default: return JSON if no redirect URL provided
42
+ return {
43
+ status: 200,
44
+ data: {
45
+ user,
46
+ token,
47
+ },
48
+ };
49
+ }
50
+ exports.formatTokenResponse = formatTokenResponse;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flink-app/oauth-plugin",
3
- "version": "0.12.1-alpha.35",
3
+ "version": "0.12.1-alpha.36",
4
4
  "description": "Flink plugin for OAuth 2.0 authentication with GitHub and Google providers",
5
5
  "scripts": {
6
6
  "test": "node --preserve-symlinks -r ts-node/register -- node_modules/jasmine/bin/jasmine --config=./spec/support/jasmine.json",
@@ -34,5 +34,5 @@
34
34
  "tsc-watch": "^4.2.9",
35
35
  "typescript": "5.4.5"
36
36
  },
37
- "gitHead": "f8e8c6565a9ca1dd3e5fdb4c2a791c99ae3ba51a"
37
+ "gitHead": "3becd47c43eb095f19f8b1ad2fa5ecbecfbd5ab6"
38
38
  }
@@ -7,6 +7,8 @@ import OAuthSessionRepo from "./repos/OAuthSessionRepo";
7
7
  import OAuthConnectionRepo from "./repos/OAuthConnectionRepo";
8
8
  import { encryptToken, decryptToken, validateEncryptionSecret } from "./utils/encryption-utils";
9
9
  import OAuthConnection from "./schemas/OAuthConnection";
10
+ import * as InitiateOAuth from "./handlers/InitiateOAuth";
11
+ import * as CallbackOAuth from "./handlers/CallbackOAuth";
10
12
 
11
13
  /**
12
14
  * OAuth Plugin Factory Function
@@ -156,10 +158,12 @@ export function oauthPlugin(options: OAuthPluginOptions): FlinkPlugin {
156
158
 
157
159
  log.info(`OAuth Plugin: Created TTL index on ${sessionsCollectionName} with ${sessionTTL}s expiration`);
158
160
 
159
- // Register handlers for each configured provider
160
- // Note: Handlers will be registered dynamically
161
- // This requires handlers to be imported, but we'll handle that in the handler files
162
- // For now, we'll skip handler registration and implement it when handlers are ready
161
+ // Register OAuth handlers
162
+ // Only register handlers if registerRoutes is enabled (default: true)
163
+ if (options.registerRoutes !== false) {
164
+ flinkApp.addHandler(InitiateOAuth);
165
+ flinkApp.addHandler(CallbackOAuth);
166
+ }
163
167
 
164
168
  log.info(`OAuth Plugin initialized with providers: ${configuredProviders.join(", ")}`);
165
169
  } catch (error) {
@@ -119,4 +119,11 @@ export interface OAuthPluginOptions {
119
119
  * Recommended: Use a dedicated encryption key from environment variables
120
120
  */
121
121
  encryptionKey?: string;
122
+
123
+ /**
124
+ * Whether to register OAuth routes automatically
125
+ * If false, you must manually handle OAuth flow
126
+ * Default: true
127
+ */
128
+ registerRoutes?: boolean;
122
129
  }