Skip to content

Commit bf8f966

Browse files
chore: Add logging to SAML endpoints (calcom#22968)
* Add logging to SAML endpoints * Update packages/features/auth/lib/next-auth-options.ts --------- Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
1 parent c64b663 commit bf8f966

6 files changed

Lines changed: 62 additions & 14 deletions

File tree

apps/web/app/api/auth/oidc/route.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@ import { NextResponse } from "next/server";
44

55
import jackson from "@calcom/features/ee/sso/lib/jackson";
66
import { HttpError } from "@calcom/lib/http-error";
7+
import logger from "@calcom/lib/logger";
78

89
// This is the callback endpoint for the OIDC provider
910
// A team must set this endpoint in the OIDC provider's configuration
1011
async function handler(req: NextRequest) {
12+
const log = logger.getSubLogger({ prefix: ["[ODIC auth]"] });
1113
const { searchParams } = req.nextUrl;
1214
const code = searchParams.get("code");
1315
const state = searchParams.get("state");
16+
const tenant = searchParams.get("tenant");
1417

1518
if (!code || !state) {
1619
return NextResponse.json({ message: "Code and state are required" }, { status: 400 });
@@ -30,6 +33,7 @@ async function handler(req: NextRequest) {
3033

3134
return NextResponse.redirect(redirect_url, 302);
3235
} catch (err) {
36+
log.error(`Error authorizing tenant ${tenant}: ${err}`);
3337
const { message, statusCode = 500 } = err as HttpError;
3438

3539
return NextResponse.json({ message }, { status: statusCode });

apps/web/app/api/auth/saml/authorize/route.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,20 @@ import { NextResponse } from "next/server";
55
import type { OAuthReq } from "@calcom/features/ee/sso/lib/jackson";
66
import jackson from "@calcom/features/ee/sso/lib/jackson";
77
import type { HttpError } from "@calcom/lib/http-error";
8+
import logger from "@calcom/lib/logger";
89

910
async function handler(req: NextRequest) {
11+
const log = logger.getSubLogger({ prefix: ["[SAML authorize]"] });
1012
const { oauthController } = await jackson();
1113

14+
const oAuthReq = Object.fromEntries(req.nextUrl.searchParams) as unknown as OAuthReq;
15+
1216
try {
13-
const { redirect_url } = await oauthController.authorize(
14-
Object.fromEntries(req.nextUrl.searchParams) as unknown as OAuthReq
15-
);
17+
const { redirect_url } = await oauthController.authorize(oAuthReq);
1618

1719
return NextResponse.redirect(redirect_url as string, 302);
1820
} catch (err) {
21+
log.error(`Error initaiting SAML login for tenant ${oAuthReq?.tenant}: ${err}`);
1922
const { message, statusCode = 500 } = err as HttpError;
2023

2124
return NextResponse.json({ message }, { status: statusCode });

apps/web/app/api/auth/saml/callback/route.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,32 @@ import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
22
import { parseRequestData } from "app/api/parseRequestData";
33
import type { NextRequest } from "next/server";
44
import { NextResponse } from "next/server";
5+
import { uuid } from "short-uuid";
56

67
import jackson from "@calcom/features/ee/sso/lib/jackson";
78
import type { SAMLResponsePayload } from "@calcom/features/ee/sso/lib/jackson";
9+
import logger from "@calcom/lib/logger";
810

911
async function handler(req: NextRequest) {
12+
const log = logger.getSubLogger({ prefix: ["[SAML callback]"] });
1013
const { oauthController } = await jackson();
1114

12-
const { redirect_url } = await oauthController.samlResponse(
13-
(await parseRequestData(req)) as SAMLResponsePayload
14-
);
15+
const requestData = (await parseRequestData(req)) as SAMLResponsePayload;
16+
17+
const { redirect_url, error } = await oauthController.samlResponse(requestData);
1518

1619
if (redirect_url) {
1720
return NextResponse.redirect(redirect_url, 302);
1821
}
1922

23+
if (error) {
24+
const uid = uuid();
25+
log.error(
26+
`Error authenticating user with error ${error} for relayState ${requestData?.RelayState} trace:${uid}`
27+
);
28+
return NextResponse.json({ message: `Error authorizing user. trace: ${uid}` }, { status: 400 });
29+
}
30+
2031
return NextResponse.json({ message: "No redirect URL provided" }, { status: 400 });
2132
}
2233

apps/web/app/api/auth/saml/token/route.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,26 @@ import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
22
import { parseRequestData } from "app/api/parseRequestData";
33
import type { NextRequest } from "next/server";
44
import { NextResponse } from "next/server";
5+
import { uuid } from "short-uuid";
56

67
import jackson from "@calcom/features/ee/sso/lib/jackson";
78
import type { OAuthTokenReq } from "@calcom/features/ee/sso/lib/jackson";
9+
import logger from "@calcom/lib/logger";
810

911
async function handler(req: NextRequest) {
1012
const { oauthController } = await jackson();
11-
const tokenResponse = await oauthController.token((await parseRequestData(req)) as OAuthTokenReq);
12-
return NextResponse.json(tokenResponse);
13+
const log = logger.getSubLogger({ prefix: ["[SAML token]"] });
14+
15+
const oauthTokenReq = (await parseRequestData(req)) as OAuthTokenReq;
16+
17+
try {
18+
const tokenResponse = await oauthController.token(oauthTokenReq);
19+
return NextResponse.json(tokenResponse);
20+
} catch (error) {
21+
const uid = uuid();
22+
log.error(`Error getting auth token for client id ${oauthTokenReq?.client_id}: ${error} trace: ${uid}`);
23+
throw new Error(`Error getting auth token with error ${error} trace: ${uid}`);
24+
}
1325
}
1426

1527
export const POST = defaultResponderForAppDir(handler);

apps/web/app/api/auth/saml/userinfo/route.ts

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,52 @@
11
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
22
import type { NextRequest } from "next/server";
33
import { NextResponse } from "next/server";
4-
import z from "zod";
4+
import { uuid } from "short-uuid";
5+
import { z } from "zod";
56

67
import jackson from "@calcom/features/ee/sso/lib/jackson";
78
import { HttpError } from "@calcom/lib/http-error";
9+
import logger from "@calcom/lib/logger";
810

911
const extractAuthToken = (req: NextRequest) => {
12+
const log = logger.getSubLogger({ prefix: ["SAML extractAuthToken"] });
13+
const uid = uuid();
1014
const authHeader = req.headers.get("authorization");
1115
const parts = (authHeader || "").split(" ");
1216
if (parts.length > 1) return parts[1];
1317

1418
// check for query param
1519
let arr: string[] = [];
16-
const { access_token } = requestQuery.parse(Object.fromEntries(req.nextUrl.searchParams));
20+
const tokenParse = requestQuery.safeParse(Object.fromEntries(req.nextUrl.searchParams));
21+
let access_token;
22+
if (!tokenParse.success) {
23+
log.error(`Error parsing request query: ${tokenParse.error} trace ${uid}`);
24+
throw new HttpError({ statusCode: 401, message: `Unauthorized trace: ${uid}` });
25+
}
26+
access_token = tokenParse.data.access_token;
1727
arr = arr.concat(access_token);
1828
if (arr[0].length > 0) return arr[0];
1929

20-
throw new HttpError({ statusCode: 401, message: "Unauthorized" });
30+
throw new HttpError({ statusCode: 401, message: `Unauthorized trace: ${uid}` });
2131
};
2232

2333
const requestQuery = z.object({
2434
access_token: z.string(),
2535
});
2636

2737
async function handler(req: NextRequest) {
38+
const log = logger.getSubLogger({ prefix: ["SAML userinfo"] });
2839
const { oauthController } = await jackson();
2940
const token = extractAuthToken(req);
30-
const userInfo = await oauthController.userInfo(token);
31-
return NextResponse.json(userInfo);
41+
42+
try {
43+
const userInfo = await oauthController.userInfo(token);
44+
return NextResponse.json(userInfo);
45+
} catch (error) {
46+
const uid = uuid();
47+
log.error(`trace: ${uid} Error getting user info from token: ${error}`);
48+
throw new Error(`Error getting user info from token. trace: ${uid}`);
49+
}
3250
}
3351

3452
export const GET = defaultResponderForAppDir(handler);

packages/features/auth/lib/next-auth-options.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { isENVDev } from "@calcom/lib/env";
3131
import logger from "@calcom/lib/logger";
3232
import { randomString } from "@calcom/lib/random";
3333
import { safeStringify } from "@calcom/lib/safeStringify";
34+
import { hashEmail } from "@calcom/lib/server/PiiHasher";
3435
import { CredentialRepository } from "@calcom/lib/server/repository/credential";
3536
import { DeploymentRepository } from "@calcom/lib/server/repository/deployment";
3637
import { OrganizationRepository } from "@calcom/lib/server/repository/organization";
@@ -48,7 +49,6 @@ import { dub } from "./dub";
4849
import { isPasswordValid } from "./isPasswordValid";
4950
import CalComAdapter from "./next-auth-custom-adapter";
5051
import { verifyPassword } from "./verifyPassword";
51-
import { hashEmail } from "@calcom/lib/server/PiiHasher";
5252

5353
const log = logger.getSubLogger({ prefix: ["next-auth-options"] });
5454
const GOOGLE_API_CREDENTIALS = process.env.GOOGLE_API_CREDENTIALS || "{}";

0 commit comments

Comments
 (0)