diff --git a/.env.example b/.env.example index f3271e560c..1c0f6152c1 100644 --- a/.env.example +++ b/.env.example @@ -1 +1,2 @@ -API_KEY_PREFIX=cal_ \ No newline at end of file +API_KEY_PREFIX=cal_ +DATABASE_URL="postgresql://postgres:@localhost:5450/calendso" diff --git a/lib/helpers/verifyApiKey.ts b/lib/helpers/verifyApiKey.ts index 6fe33c6ad3..008f3dc4f4 100644 --- a/lib/helpers/verifyApiKey.ts +++ b/lib/helpers/verifyApiKey.ts @@ -4,31 +4,31 @@ import { hashAPIKey } from "@calcom/ee/lib/api/apiKeys"; import prisma from "@calcom/prisma"; // Used to check if the API key is not expired, could be extracted if reused. but not for now. -export const dateInPast = function (firstDate: Date, secondDate: Date) { - if (firstDate.setHours(0, 0, 0, 0) <= secondDate.setHours(0, 0, 0, 0)) { +export const dateInPast = function (date: Date) { + const now = new Date(); + if (now.setHours(0, 0, 0, 0) <= date.setHours(0, 0, 0, 0)) { return true; } }; -const today = new Date(); // This verifies the API key and sets the user if it is valid. export const verifyApiKey: NextMiddleware = async (req, res, next) => { - if (!req.query.apiKey) res.status(401).json({ message: "No API key provided" }); - + if (!req.query.apiKey) res.status(401).json({ message: "No api key provided" }); + // We remove the prefix from the user provided api_key. If no env set default to "cal_" const strippedApiKey = `${req.query.apiKey}`.replace(process.env.API_KEY_PREFIX || "cal_", ""); + // Hash the key again before matching against the database records. const hashedKey = hashAPIKey(strippedApiKey); - - await prisma.apiKey - .findUnique({ where: { hashedKey } }) - .then(async (apiKey) => { - if (!apiKey) { - res.status(401).json({ error: "You did not provide an api key" }); - throw new Error("No api key found"); - } - if (apiKey.userId) res.setHeader("X-Calcom-User-ID", apiKey.userId); - if (apiKey.expiresAt && apiKey.userId && dateInPast(today, apiKey.expiresAt)) await next(); - }) - .catch((error) => { - res.status(401).json({ error: "Your api key is not valid" }); - }); + // Check if the hashed api key exists in database. + await prisma.apiKey.findUnique({ where: { hashedKey } }).then(async (apiKey) => { + // If we cannot find any api key. Throw a 401 Unauthorized. + if (!apiKey) res.status(401).json({ error: "Your api key is not valid" }); + if (apiKey && apiKey.expiresAt && dateInPast(apiKey.expiresAt) && apiKey.userId) { + // Right now API Keys are user centric, we only allow resources related to this userId throughout the application. + // if the api key is not expired, and the user id is present in the database. + // Set the user in the request. as x-calcom-user-id. + res.setHeader("X-Calcom-User-ID", apiKey.userId); + // Pass the request to the next middleware. + await next(); + } + }); };