MCPcopy Create free account
hub / github.com/adcontextprotocol/adcp / createAgentOAuthRouter

Function createAgentOAuthRouter

server/src/routes/agent-oauth.ts:199–530  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

197 * Create agent OAuth routes
198 */
199export function createAgentOAuthRouter(): Router {
200 const router = Router();
201 const agentContextDb = new AgentContextDatabase();
202
203 // Get the base URL for callbacks
204 const getCallbackUrl = (req: Request): string => {
205 const protocol = req.headers['x-forwarded-proto'] || req.protocol;
206 const host = req.headers['x-forwarded-host'] || req.get('host');
207 return `${protocol}://${host}/api/oauth/agent/callback`;
208 };
209
210 /**
211 * Start OAuth flow for an agent
212 * GET /api/oauth/agent/start?agent_context_id=...
213 */
214 router.get('/start', requireAuth, async (req: Request, res: Response) => {
215 try {
216 const { agent_context_id, pending_task, pending_params, return_to } = req.query;
217 const returnTo = sanitizeReturnTo(return_to);
218
219 // codeql[js/user-controlled-bypass] - agent context ID from query is validated and used as a lookup key
220 if (!agent_context_id || typeof agent_context_id !== 'string') {
221 return res.status(400).json({ error: 'agent_context_id is required' });
222 }
223
224 // Parse pending request context (for auto-retry after OAuth)
225 let pendingRequest: { task: string; params: Record<string, unknown> } | undefined;
226 if (pending_task && typeof pending_task === 'string') {
227 try {
228 const params = pending_params && typeof pending_params === 'string'
229 ? JSON.parse(decodeURIComponent(pending_params))
230 : {};
231 pendingRequest = { task: pending_task, params };
232 } catch (error) {
233 logger.warn({ error, pending_params }, 'Failed to parse pending request params - continuing without retry context');
234 }
235 }
236
237 // Get user ID from authenticated request
238 const userId = req.user?.id;
239 if (!userId) {
240 return res.status(401).json({ error: 'Not authenticated' });
241 }
242
243 // Get member context for organization
244 const memberContext = await getWebMemberContext(userId);
245 if (!memberContext?.organization?.workos_organization_id) {
246 return res.status(401).json({ error: 'No organization found' });
247 }
248
249 const organizationId = memberContext.organization.workos_organization_id;
250
251 // Get agent context
252 const agentContext = await agentContextDb.getById(agent_context_id);
253 if (!agentContext) {
254 return res.status(404).json({ error: 'Agent context not found' });
255 }
256

Callers 1

setupRoutesMethod · 0.85

Calls 15

getByIdMethod · 0.95
getOAuthClientMethod · 0.95
clearOAuthClientMethod · 0.95
saveOAuthClientMethod · 0.95
saveOAuthTokensMethod · 0.95
removeOAuthTokensMethod · 0.95
hasValidOAuthTokensMethod · 0.95
sanitizeReturnToFunction · 0.85
getWebMemberContextFunction · 0.85
getCallbackUrlFunction · 0.85
registerOAuthClientFunction · 0.85
generatePKCEFunction · 0.85

Tested by

no test coverage detected