diff --git a/apps/web/app/api/auth/oauth/me/route.ts b/apps/web/app/api/auth/oauth/me/route.ts new file mode 100644 index 0000000000..9dc15e5c59 --- /dev/null +++ b/apps/web/app/api/auth/oauth/me/route.ts @@ -0,0 +1,18 @@ +import { NextResponse } from "next/server"; +import type { NextRequest } from "next/server"; + +import isAuthorized from "@calcom/features/auth/lib/oAuthAuthorization"; + +async function handler(req: NextRequest) { + const requiredScopes = ["READ_PROFILE"]; + const token = req.headers.get("authorization")?.split(" ")[1] || ""; + const account = await isAuthorized(token, requiredScopes); + + if (!account) { + return NextResponse.json({ message: "Unauthorized" }, { status: 401 }); + } + + return NextResponse.json({ username: account.name }, { status: 201 }); +} + +export { handler as GET, handler as POST }; diff --git a/apps/web/pages/api/auth/oauth/refreshToken.ts b/apps/web/app/api/auth/oauth/refreshToken/route.ts similarity index 62% rename from apps/web/pages/api/auth/oauth/refreshToken.ts rename to apps/web/app/api/auth/oauth/refreshToken/route.ts index 309c2d5c72..591ce4e541 100644 --- a/apps/web/pages/api/auth/oauth/refreshToken.ts +++ b/apps/web/app/api/auth/oauth/refreshToken/route.ts @@ -1,23 +1,16 @@ import jwt from "jsonwebtoken"; -import type { NextApiRequest, NextApiResponse } from "next"; +import { NextResponse } from "next/server"; +import type { NextRequest } from "next/server"; import prisma from "@calcom/prisma"; import { generateSecret } from "@calcom/trpc/server/routers/viewer/oAuth/addClient.handler"; import type { OAuthTokenPayload } from "@calcom/types/oauth"; -export default async function handler(req: NextApiRequest, res: NextApiResponse) { - if (req.method !== "POST") { - res.status(405).json({ message: "Invalid method" }); - return; - } - - const refreshToken = req.headers.authorization?.split(" ")[1] || ""; - - const { client_id, client_secret, grant_type } = req.body; +export async function POST(req: NextRequest) { + const { client_id, client_secret, grant_type } = await req.json(); if (grant_type !== "refresh_token") { - res.status(400).json({ message: "grant type invalid" }); - return; + return NextResponse.json({ message: "grant type invalid" }, { status: 400 }); } const [hashedSecret] = generateSecret(client_secret); @@ -33,8 +26,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) }); if (!client) { - res.status(401).json({ message: "Unauthorized" }); - return; + return NextResponse.json({ message: "Unauthorized" }, { status: 401 }); } const secretKey = process.env.CALENDSO_ENCRYPTION_KEY || ""; @@ -42,15 +34,14 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) let decodedRefreshToken: OAuthTokenPayload; try { + const refreshToken = req.headers.get("authorization")?.split(" ")[1] || ""; decodedRefreshToken = jwt.verify(refreshToken, secretKey) as OAuthTokenPayload; } catch { - res.status(401).json({ message: "Unauthorized" }); - return; + return NextResponse.json({ message: "Unauthorized" }, { status: 401 }); } if (!decodedRefreshToken || decodedRefreshToken.token_type !== "Refresh Token") { - res.status(401).json({ message: "Unauthorized" }); - return; + return NextResponse.json({ message: "Unauthorized" }, { status: 401 }); } const payload: OAuthTokenPayload = { @@ -65,5 +56,5 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) expiresIn: 1800, // 30 min }); - res.status(200).json({ access_token }); + return NextResponse.json({ access_token }, { status: 200 }); } diff --git a/apps/web/pages/api/auth/oauth/token.ts b/apps/web/app/api/auth/oauth/token/route.ts similarity index 75% rename from apps/web/pages/api/auth/oauth/token.ts rename to apps/web/app/api/auth/oauth/token/route.ts index 07b91fdc9d..bc956fc87f 100644 --- a/apps/web/pages/api/auth/oauth/token.ts +++ b/apps/web/app/api/auth/oauth/token/route.ts @@ -1,21 +1,16 @@ import jwt from "jsonwebtoken"; -import type { NextApiRequest, NextApiResponse } from "next"; +import { NextResponse } from "next/server"; +import type { NextRequest } from "next/server"; import prisma from "@calcom/prisma"; import { generateSecret } from "@calcom/trpc/server/routers/viewer/oAuth/addClient.handler"; import type { OAuthTokenPayload } from "@calcom/types/oauth"; -export default async function handler(req: NextApiRequest, res: NextApiResponse) { - if (req.method !== "POST") { - res.status(405).json({ message: "Invalid method" }); - return; - } - - const { code, client_id, client_secret, grant_type, redirect_uri } = req.body; +export async function POST(req: NextRequest) { + const { code, client_id, client_secret, grant_type, redirect_uri } = await req.json(); if (grant_type !== "authorization_code") { - res.status(400).json({ message: "grant_type invalid" }); - return; + return NextResponse.json({ message: "grant_type invalid" }, { status: 400 }); } const [hashedSecret] = generateSecret(client_secret); @@ -31,8 +26,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) }); if (!client || client.redirectUri !== redirect_uri) { - res.status(401).json({ message: "Unauthorized" }); - return; + return NextResponse.json({ message: "Unauthorized" }, { status: 401 }); } const accessCode = await prisma.accessCode.findFirst({ @@ -45,7 +39,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) }, }); - //delete all expired accessCodes + the one that is used here + // Delete all expired accessCodes + the one that is used here await prisma.accessCode.deleteMany({ where: { OR: [ @@ -63,8 +57,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) }); if (!accessCode) { - res.status(401).json({ message: "Unauthorized" }); - return; + return NextResponse.json({ message: "Unauthorized" }, { status: 401 }); } const secretKey = process.env.CALENDSO_ENCRYPTION_KEY || ""; @@ -93,5 +86,5 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) expiresIn: 30 * 24 * 60 * 60, // 30 days }); - res.status(200).json({ access_token, refresh_token }); + return NextResponse.json({ access_token, refresh_token }, { status: 200 }); } diff --git a/apps/web/pages/api/auth/oauth/me.ts b/apps/web/pages/api/auth/oauth/me.ts deleted file mode 100644 index c8efb71cd9..0000000000 --- a/apps/web/pages/api/auth/oauth/me.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { NextApiRequest, NextApiResponse } from "next"; - -import isAuthorized from "@calcom/features/auth/lib/oAuthAuthorization"; - -export default async function handler(req: NextApiRequest, res: NextApiResponse) { - const requiredScopes = ["READ_PROFILE"]; - - const account = await isAuthorized(req, requiredScopes); - - if (!account) { - return res.status(401).json({ message: "Unauthorized" }); - } - return res.status(201).json({ username: account.name }); -} diff --git a/packages/app-store/zapier/lib/validateAccountOrApiKey.ts b/packages/app-store/zapier/lib/validateAccountOrApiKey.ts index 151be97071..113513c503 100644 --- a/packages/app-store/zapier/lib/validateAccountOrApiKey.ts +++ b/packages/app-store/zapier/lib/validateAccountOrApiKey.ts @@ -8,7 +8,8 @@ export async function validateAccountOrApiKey(req: NextApiRequest, requiredScope const apiKey = req.query.apiKey as string; if (!apiKey) { - const authorizedAccount = await isAuthorized(req, requiredScopes); + const token = req.headers.authorization?.split(" ")[1] || ""; + const authorizedAccount = await isAuthorized(token, requiredScopes); if (!authorizedAccount) throw new HttpError({ statusCode: 401, message: "Unauthorized" }); return { account: authorizedAccount, appApiKey: undefined }; } diff --git a/packages/features/auth/lib/oAuthAuthorization.ts b/packages/features/auth/lib/oAuthAuthorization.ts index eb38738729..0d0e0e1cd4 100644 --- a/packages/features/auth/lib/oAuthAuthorization.ts +++ b/packages/features/auth/lib/oAuthAuthorization.ts @@ -1,11 +1,9 @@ import jwt from "jsonwebtoken"; -import type { NextApiRequest } from "next"; import prisma from "@calcom/prisma"; import type { OAuthTokenPayload } from "@calcom/types/oauth"; -export default async function isAuthorized(req: NextApiRequest, requiredScopes: string[] = []) { - const token = req.headers.authorization?.split(" ")[1] || ""; +export default async function isAuthorized(token: string, requiredScopes: string[] = []) { let decodedToken: OAuthTokenPayload; try { decodedToken = jwt.verify(token, process.env.CALENDSO_ENCRYPTION_KEY || "") as OAuthTokenPayload;