Make sure that absolute URL is of WEBAPP only (#2624)
parent
59c0784cd6
commit
a224a46654
|
@ -7,6 +7,7 @@ import { useRouter } from "next/router";
|
|||
import { useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
|
||||
import { getSafeRedirectUrl } from "@calcom/lib/getSafeRedirectUrl";
|
||||
import { Alert } from "@calcom/ui/Alert";
|
||||
import Button from "@calcom/ui/Button";
|
||||
import { EmailField, Form, PasswordField } from "@calcom/ui/form/fields";
|
||||
|
@ -61,12 +62,15 @@ export default function Login({
|
|||
|
||||
let callbackUrl = typeof router.query?.callbackUrl === "string" ? router.query.callbackUrl : "";
|
||||
|
||||
// If not absolute URL, make it absolute
|
||||
if (/"\//.test(callbackUrl)) callbackUrl = callbackUrl.substring(1);
|
||||
|
||||
// If not absolute URL, make it absolute
|
||||
if (!/^https?:\/\//.test(callbackUrl)) {
|
||||
callbackUrl = `${WEBAPP_URL}/${callbackUrl}`;
|
||||
}
|
||||
|
||||
callbackUrl = getSafeRedirectUrl(callbackUrl);
|
||||
|
||||
const LoginFooter = (
|
||||
<span>
|
||||
{t("dont_have_an_account")}{" "}
|
||||
|
|
|
@ -2,6 +2,7 @@ import { google } from "googleapis";
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { getSafeRedirectUrl } from "@calcom/lib/getSafeRedirectUrl";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { decodeOAuthState } from "../../_utils/decodeOAuthState";
|
||||
|
@ -10,7 +11,6 @@ const credentials = process.env.GOOGLE_API_CREDENTIALS;
|
|||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
const { code } = req.query;
|
||||
|
||||
if (code && typeof code !== "string") {
|
||||
res.status(400).json({ message: "`code` must be a string" });
|
||||
return;
|
||||
|
@ -19,7 +19,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||
res.status(400).json({ message: "There are no Google Credentials installed." });
|
||||
return;
|
||||
}
|
||||
|
||||
const { client_secret, client_id } = JSON.parse(credentials).web;
|
||||
const redirect_uri = WEBAPP_URL + "/api/integrations/googlecalendar/callback";
|
||||
|
||||
|
@ -41,5 +40,5 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||
},
|
||||
});
|
||||
const state = decodeOAuthState(req);
|
||||
res.redirect(state?.returnTo ?? "/apps/installed");
|
||||
res.redirect(getSafeRedirectUrl(state?.returnTo) ?? "/apps/installed");
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import { TokenResponseIF } from "@hubspot/api-client/lib/codegen/oauth/models/To
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { getSafeRedirectUrl } from "@calcom/lib/getSafeRedirectUrl";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { decodeOAuthState } from "../../_utils/decodeOAuthState";
|
||||
|
@ -52,5 +53,5 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||
});
|
||||
|
||||
const state = decodeOAuthState(req);
|
||||
res.redirect(state?.returnTo ?? "/apps/installed");
|
||||
res.redirect(getSafeRedirectUrl(state?.returnTo) ?? "/apps/installed");
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { BASE_URL } from "@calcom/lib/constants";
|
||||
import { getSafeRedirectUrl } from "@calcom/lib/getSafeRedirectUrl";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { decodeOAuthState } from "../../_utils/decodeOAuthState";
|
||||
|
@ -62,5 +63,5 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||
});
|
||||
|
||||
const state = decodeOAuthState(req);
|
||||
return res.redirect(state?.returnTo ?? "/apps/installed");
|
||||
return res.redirect(getSafeRedirectUrl(state?.returnTo) ?? "/apps/installed");
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { BASE_URL } from "@calcom/lib/constants";
|
||||
import { getSafeRedirectUrl } from "@calcom/lib/getSafeRedirectUrl";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { decodeOAuthState } from "../../_utils/decodeOAuthState";
|
||||
|
@ -63,5 +64,5 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||
});
|
||||
|
||||
const state = decodeOAuthState(req);
|
||||
return res.redirect(state?.returnTo ?? "/apps/installed");
|
||||
return res.redirect(getSafeRedirectUrl(state?.returnTo) ?? "/apps/installed");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
import { WEBAPP_URL, WEBSITE_URL } from "@calcom/lib/constants";
|
||||
|
||||
// It ensures that redirection URL safe where it is accepted through a query params or other means where user can change it.
|
||||
export const getSafeRedirectUrl = (url: string | undefined) => {
|
||||
url = url || "";
|
||||
if (url.search(/^https?:\/\//) === -1) {
|
||||
throw new Error("Pass an absolute URL");
|
||||
}
|
||||
|
||||
// Avoid open redirection security vulnerability
|
||||
if (!url.startsWith(WEBAPP_URL) && !url.startsWith(WEBSITE_URL)) {
|
||||
url = `${WEBAPP_URL}/`;
|
||||
}
|
||||
|
||||
return url;
|
||||
};
|
Loading…
Reference in New Issue