const express = require('express'); const jwt = require('jsonwebtoken'); const { getAccessToken } = require('~/server/services/TokenService'); const { logger, getFlowStateManager } = require('~/config'); const { getLogStores } = require('~/cache'); const router = express.Router(); const JWT_SECRET = process.env.JWT_SECRET; /** * Handles the OAuth callback and exchanges the authorization code for tokens. * * @route GET /actions/:action_id/oauth/callback * @param {string} req.params.action_id - The ID of the action. * @param {string} req.query.code - The authorization code returned by the provider. * @param {string} req.query.state - The state token to verify the authenticity of the request. * @returns {void} Sends a success message after updating the action with OAuth tokens. */ router.get('/:action_id/oauth/callback', async (req, res) => { const { action_id } = req.params; const { code, state } = req.query; const flowManager = await getFlowStateManager(getLogStores); let identifier = action_id; try { let decodedState; try { decodedState = jwt.verify(state, JWT_SECRET); } catch (err) { await flowManager.failFlow(identifier, 'oauth', 'Invalid or expired state parameter'); return res.status(400).send('Invalid or expired state parameter'); } if (decodedState.action_id !== action_id) { await flowManager.failFlow(identifier, 'oauth', 'Mismatched action ID in state parameter'); return res.status(400).send('Mismatched action ID in state parameter'); } if (!decodedState.user) { await flowManager.failFlow(identifier, 'oauth', 'Invalid user ID in state parameter'); return res.status(400).send('Invalid user ID in state parameter'); } identifier = `${decodedState.user}:${action_id}`; const flowState = await flowManager.getFlowState(identifier, 'oauth'); if (!flowState) { throw new Error('OAuth flow not found'); } const tokenData = await getAccessToken({ code, userId: decodedState.user, identifier, client_url: flowState.metadata.client_url, redirect_uri: flowState.metadata.redirect_uri, /** Encrypted values */ encrypted_oauth_client_id: flowState.metadata.encrypted_oauth_client_id, encrypted_oauth_client_secret: flowState.metadata.encrypted_oauth_client_secret, }); await flowManager.completeFlow(identifier, 'oauth', tokenData); res.send(`
Your authentication was successful. This window will close in 3 seconds.