From 1731202222e57c5d1ccc359b979280eec2ee836a Mon Sep 17 00:00:00 2001 From: Hariom Date: Thu, 18 Jul 2024 12:11:00 +0530 Subject: [PATCH] Check URL --- packages/app-store/zoho-bigin/api/callback.ts | 24 +++++++++++++++ packages/app-store/zohocrm/api/callback.ts | 30 ++++++++++++++++--- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/packages/app-store/zoho-bigin/api/callback.ts b/packages/app-store/zoho-bigin/api/callback.ts index b2241a66b39563..dba79369555a2f 100644 --- a/packages/app-store/zoho-bigin/api/callback.ts +++ b/packages/app-store/zoho-bigin/api/callback.ts @@ -11,6 +11,20 @@ import createOAuthAppCredential from "../../_utils/oauth/createOAuthAppCredentia import { decodeOAuthState } from "../../_utils/oauth/decodeOAuthState"; import appConfig from "../config.json"; +function isAuthorizedAccountsServerUrl(accountsServer: string) { + // As per https://www.zoho.com/crm/developer/docs/api/v6/multi-dc.html#:~:text=US:%20https://accounts.zoho,https://accounts.zohocloud.ca&text=The%20%22location=us%22%20parameter,domain%20in%20all%20API%20endpoints.&text=You%20must%20make%20the%20authorization,.zoho.com.cn. + const authorizedAccountServers = [ + "https://accounts.zoho.com", + "https://accounts.zoho.eu", + "https://accounts.zoho.in", + "https://accounts.zoho.com.cn", + "https://accounts.zoho.jp", + "https://accounts.zohocloud.ca", + "https://accounts.zoho.com.au", + ]; + return authorizedAccountServers.includes(accountsServer); +} + export default async function handler(req: NextApiRequest, res: NextApiResponse) { const { code, "accounts-server": accountsServer } = req.query; const state = decodeOAuthState(req); @@ -20,6 +34,16 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) return; } + if (!accountsServer || typeof accountsServer !== "string") { + res.status(400).json({ message: "`accounts-server` is required and must be a string" }); + return; + } + + if (!isAuthorizedAccountsServerUrl(accountsServer)) { + res.status(400).json({ message: "`accounts-server` is not authorized" }); + return; + } + if (!req.session?.user?.id) { res.status(401).json({ message: "You must be logged in to do this" }); return; diff --git a/packages/app-store/zohocrm/api/callback.ts b/packages/app-store/zohocrm/api/callback.ts index 91a2ea7f41af18..8432d957a22753 100644 --- a/packages/app-store/zohocrm/api/callback.ts +++ b/packages/app-store/zohocrm/api/callback.ts @@ -13,15 +13,38 @@ import appConfig from "../config.json"; let client_id = ""; let client_secret = ""; +function isAuthorizedAccountsServerUrl(accountsServer: string) { + // As per https://www.zoho.com/crm/developer/docs/api/v6/multi-dc.html#:~:text=US:%20https://accounts.zoho,https://accounts.zohocloud.ca&text=The%20%22location=us%22%20parameter,domain%20in%20all%20API%20endpoints.&text=You%20must%20make%20the%20authorization,.zoho.com.cn. + const authorizedAccountServers = [ + "https://accounts.zoho.com", + "https://accounts.zoho.eu", + "https://accounts.zoho.in", + "https://accounts.zoho.com.cn", + "https://accounts.zoho.jp", + "https://accounts.zohocloud.ca", + "https://accounts.zoho.com.au", + ]; + return authorizedAccountServers.includes(accountsServer); +} export default async function handler(req: NextApiRequest, res: NextApiResponse) { - const { code } = req.query; + const { code, "accounts-server": accountsServer } = req.query; if (code === undefined && typeof code !== "string") { res.status(400).json({ message: "`code` must be a string" }); return; } + if (!accountsServer || typeof accountsServer !== "string") { + res.status(400).json({ message: "`accounts-server` is required and must be a string" }); + return; + } + + if (!isAuthorizedAccountsServerUrl(accountsServer)) { + res.status(400).json({ message: "`accounts-server` is not authorized" }); + return; + } + if (!req.session?.user?.id) { return res.status(401).json({ message: "You must be logged in to do this" }); } @@ -31,8 +54,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) if (typeof appKeys.client_secret === "string") client_secret = appKeys.client_secret; if (!client_id) return res.status(400).json({ message: "Zoho Crm consumer key missing." }); if (!client_secret) return res.status(400).json({ message: "Zoho Crm consumer secret missing." }); - - const url = `${req.query["accounts-server"]}/oauth/v2/token`; + const url = `${accountsServer}/oauth/v2/token`; const redirectUri = `${WEBAPP_URL}/api/integrations/zohocrm/callback`; const formData = { grant_type: "authorization_code", @@ -51,7 +73,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) }); // set expiry date as offset from current time. zohoCrmTokenInfo.data.expiryDate = Math.round(Date.now() + 60 * 60); - zohoCrmTokenInfo.data.accountServer = req.query["accounts-server"]; + zohoCrmTokenInfo.data.accountServer = accountsServer; await createOAuthAppCredential({ appId: appConfig.slug, type: appConfig.type }, zohoCrmTokenInfo.data, req);