Add Zoom OAuth Integration + Zoom Transcript Loader#239
Add Zoom OAuth Integration + Zoom Transcript Loader#239bradtaylorsf wants to merge 12 commits intostagingfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
| const router = express.Router() | ||
|
|
||
| // GET /api/v1/zoom-auth | ||
| router.get('/zoom-auth', zoomAuthController.authenticate) |
Check failure
Code scanning / CodeQL
Missing rate limiting High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 7 months ago
To address the missing rate limiting, we will introduce a rate-limiting middleware specifically for the zoom-auth route. We'll use the well-known express-rate-limit package, which is designed for this purpose. A rate limiter will be configured to allow a reasonable number of requests per minute for the /zoom-auth route. This ensures that the endpoint is protected from excessive or abusive traffic while maintaining legitimate user access.
Steps:
- Install the
express-rate-limitpackage if it is not already included in the project. - Import the
express-rate-limitpackage into the file. - Configure a rate limiter with appropriate settings (e.g., 100 requests per 15 minutes).
- Apply the rate limiter specifically to the
/zoom-authroute.
| @@ -1,11 +1,17 @@ | ||
| import express from 'express' | ||
| import zoomAuthController from '../../controllers/zoom-auth/index' | ||
| import passport from 'passport' | ||
|
|
||
| import rateLimit from 'express-rate-limit' | ||
| const router = express.Router() | ||
|
|
||
| // Rate limiter configuration for zoom-auth | ||
| const zoomAuthRateLimiter = rateLimit({ | ||
| windowMs: 15 * 60 * 1000, // 15 minutes | ||
| max: 100, // limit each IP to 100 requests per windowMs | ||
| }) | ||
|
|
||
| // GET /api/v1/zoom-auth | ||
| router.get('/zoom-auth', zoomAuthController.authenticate) | ||
| router.get('/zoom-auth', zoomAuthRateLimiter, zoomAuthController.authenticate) | ||
|
|
||
| // GET /api/v1/zoom-auth/callback | ||
| router.get( |
|
BWS on AAI Local is showing the following vars, is BWS missing one? According to the PR here its stating that a callback url is required, is this different on staging and production and hard coded in so we're just using ngrok locally to check? ZOOM_CLIENT_ID |
|
@diecoscai Please look at this and test it and fix any remaining issues with being able to pull zoom meetings in from using OAuth. thanks! |
|
It will need to be rebased, btw |
fe8567f to
45af0b8
Compare
ba4c04e to
9ecb53e
Compare
| const response = await axios.get(endpoint, { | ||
| headers: { | ||
| Authorization: `Bearer ${params.accessToken}`, | ||
| 'Content-Type': 'application/json' | ||
| }, | ||
| params: { | ||
| from: fromDate, | ||
| to: toDate, | ||
| page_size: params.pageSize || 30 | ||
| } | ||
| }) |
Check failure
Code scanning / CodeQL
Server-side request forgery Critical
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 7 months ago
To mitigate the SSRF vulnerability, we will restrict user input by:
- Validating
params.accountIdandparams.userIdagainst an allow-list or ensuring they conform to a strict format (e.g., alphanumeric and specific lengths). - Optionally, we can hardcode or derive
accountIdanduserIdfrom a trusted source rather than directly using user-provided values.
For this fix:
- Add validation logic for
params.accountIdandparams.userIdto ensure they are safe. - Reject requests with inappropriate or malicious values.
- The validation logic will be added in the
getOrganizationMeetingsfunction before constructing theendpoint.
| @@ -146,9 +146,19 @@ | ||
| const fromDate = params.fromDate || defaultFromDate.toISOString().split('T')[0] | ||
| const toDate = params.toDate || new Date().toISOString().split('T')[0] | ||
|
|
||
| // Validate accountId and userId | ||
| const accountId = params.accountId; | ||
| if (!/^[a-zA-Z0-9_-]+$/.test(accountId)) { | ||
| throw new InternalFlowiseError(StatusCodes.BAD_REQUEST, 'Invalid Account ID') | ||
| } | ||
|
|
||
| const userId = params.userId || 'me'; | ||
| if (userId !== 'me' && !/^[a-zA-Z0-9_-]+$/.test(userId)) { | ||
| throw new InternalFlowiseError(StatusCodes.BAD_REQUEST, 'Invalid User ID') | ||
| } | ||
|
|
||
| // Use account-level endpoint for organization meetings | ||
| const userId = params.userId || 'me' | ||
| const endpoint = `https://api.zoom.us/v2/accounts/${params.accountId}/users/${userId}/recordings` | ||
| const endpoint = `https://api.zoom.us/v2/accounts/${accountId}/users/${userId}/recordings` | ||
|
|
||
| const response = await axios.get(endpoint, { | ||
| headers: { |
…ist hidden unless no chief sidekick, and left navbar opens by default (closes #316)
- Add user context parameter to saveCustomTemplate service method - Pass req.user from controller to service for proper authorization - Add enforceAbility middleware to custom template route - Fix 'Unauthorized public access to non-public chatflow' error Resolves: Diego Ticket 1 - Template save functionality
- Simplify generateExportFlowData to pass complete chatflow object - Add 404 error handling for missing chatflows - Clean up marketplace-specific descriptions on import - Improve error handling in canvas flow loading Resolves: Diego Ticket 1 - Template export functionality
… approach This PR refactors the default chatflow redirection mechanism by removing server-side cookie dependency and implementing a cleaner client-side solution. ## Changes Made ### Removed Cookie Implementation - Removed defaultChatflowId cookie reading from getCachedSession.ts - Removed cookie setting functionality from authentication middleware - Eliminated server-side cookie dependency for default chatflow handling ### Implemented Client-Side Solution - Added ChatRedirectHandler component for managing chat redirects - Created useRedirectToDefaultChatflow hook for redirect logic - Added auth API client for /auth/me endpoint calls - Enhanced authentication middleware with direct /auth/me endpoint ### Architecture Improvements - Replaced server-side cookie management with API-based approach - Improved debugging capabilities with client-side logic - Reduced security concerns related to cookie handling - Simplified state management by removing cookie dependencies ## Benefits - Better separation of concerns (client handles UI, server provides data) - Easier debugging and testing of redirect logic - No cookie security implications - More maintainable and modern approach - Cleaner code architecture
| router.get('/templates/:id', marketplacesController.getMarketplaceTemplate) | ||
|
|
||
| router.post('/custom', marketplacesController.saveCustomTemplate) | ||
| router.post('/custom', enforceAbility('CustomTemplate'), marketplacesController.saveCustomTemplate) |
Check failure
Code scanning / CodeQL
Missing rate limiting High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 7 months ago
To address the issue, we will add rate limiting to the route handler using the express-rate-limit package. This package allows us to define a maximum number of requests per time window for specific routes.
Steps to fix:
- Install the
express-rate-limitpackage if it is not already installed. - Import the package in the file.
- Define a rate limiter with appropriate settings (e.g., maximum requests per minute).
- Apply the rate limiter middleware to the specific route handler (
router.post('/custom')).
This fix ensures that the route is protected against abuse while maintaining its functionality.
| @@ -3,4 +3,10 @@ | ||
| import enforceAbility from '../../middlewares/authentication/enforceAbility' | ||
| import rateLimit from 'express-rate-limit' | ||
| const router = express.Router() | ||
|
|
||
| const limiter = rateLimit({ | ||
| windowMs: 15 * 60 * 1000, // 15 minutes | ||
| max: 100, // Limit each IP to 100 requests per windowMs | ||
| }); | ||
|
|
||
| // READ | ||
| @@ -9,3 +15,3 @@ | ||
|
|
||
| router.post('/custom', enforceAbility('CustomTemplate'), marketplacesController.saveCustomTemplate) | ||
| router.post('/custom', limiter, enforceAbility('CustomTemplate'), marketplacesController.saveCustomTemplate) | ||
|
|
97e6246 to
d3f323a
Compare
|
919192f to
67551b8
Compare


Zoom OAuth2 Integration PR
This PR introduces full OAuth2 support for Zoom, enabling users to authenticate their Zoom accounts and pull transcript recordings from selected Zoom meetings. It includes the UI, backend, and document loader components to support this integration end-to-end.
✅ Features Included
1. Zoom OAuth Credential Integration
New credential type:
ZoomOAuthOAuth login flow via
/zoom-authand/zoom-auth/callbackroutesAuthenticated user details + tokens are stored in a credential object:
zoomAccessTokenzoomRefreshTokenprovider,providerId,email,fullName2. Zoom Transcript Document Loader
.vtttranscript files from the meeting recordings3. UI Components
ZoomAuthButton: Trigger Zoom OAuth popupZoomMeetingPicker: Dialog for selecting past meetings with available recordings📦 New Dependencies
Added to
packages/server/package.json:🔐 New Environment Variables
Add the following to your
.envfile or hosting provider config:This PR includes a sample Zoom App configured at:
👉 [Zoom Marketplace – Registered App](https://marketplace.zoom.us/develop/applications/DtYZJ0veRjCMo4BCuWDNbg/information)
🔍 Local Testing with Ngrok
To test OAuth locally:
Run your local server:
Start ngrok on the same port:
Copy the HTTPS ngrok URL and update your .env:
Update your Zoom App’s Redirect URL for OAuth in the [Zoom App Marketplace](https://marketplace.zoom.us/develop/applications/DtYZJ0veRjCMo4BCuWDNbg/information) to match your ngrok callback URL.
🧪 How to Test