Skip to content

Commit a313aa9

Browse files
committed
fix: include http.client_ip in all auth event logs
1 parent 411a589 commit a313aa9

File tree

1 file changed

+34
-0
lines changed

1 file changed

+34
-0
lines changed

src/middleware/auth.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,29 @@ import { eq } from "drizzle-orm";
66
import { logger } from "../lib/logger";
77
import type { ClerkUserData, ClerkJWTPayload, UserUpdateData, DatabaseError } from "../types";
88

9+
/**
10+
* Extract client IP from request headers (supports proxies like Cloudflare, ALB)
11+
*/
12+
const getClientIp = (c: Context): string => {
13+
// Check headers in order of priority
14+
const xForwardedFor = c.req.header("x-forwarded-for");
15+
if (xForwardedFor) {
16+
// First IP in the list is the original client
17+
return xForwardedFor.split(",")[0].trim();
18+
}
19+
20+
const xRealIp = c.req.header("x-real-ip");
21+
if (xRealIp) return xRealIp;
22+
23+
const cfConnectingIp = c.req.header("cf-connecting-ip");
24+
if (cfConnectingIp) return cfConnectingIp;
25+
26+
// Fallback to socket remote address
27+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
28+
const socket = (c.req.raw as any).socket;
29+
return socket?.remoteAddress || "unknown";
30+
};
31+
932
if (!process.env.CLERK_SECRET_KEY) {
1033
throw new Error(
1134
"Missing Clerk Secret Key - Please add CLERK_SECRET_KEY to your environment variables"
@@ -49,6 +72,7 @@ const extractAndVerifyClerkToken = async (c: Context): Promise<ClerkUserData | n
4972
};
5073

5174
export const authMiddleware = async (c: Context, next: Next) => {
75+
const clientIp = getClientIp(c);
5276
const userData = await extractAndVerifyClerkToken(c);
5377

5478
if (!userData) {
@@ -57,6 +81,7 @@ export const authMiddleware = async (c: Context, next: Next) => {
5781
event_type: "auth_failure",
5882
reason: "Invalid or missing token",
5983
path: new URL(c.req.url).pathname,
84+
"http.client_ip": clientIp,
6085
});
6186
throw new HTTPException(401, {
6287
message: "Authentication required",
@@ -77,6 +102,7 @@ export const authMiddleware = async (c: Context, next: Next) => {
77102
error: error instanceof Error ? error.message : String(error),
78103
type: "database_error",
79104
event_type: "database_error",
105+
"http.client_ip": clientIp,
80106
},
81107
error instanceof Error ? error : undefined
82108
);
@@ -110,6 +136,7 @@ export const authMiddleware = async (c: Context, next: Next) => {
110136
logger.info("[AUTH] New user - fetching details from Clerk", {
111137
userId: userData.id,
112138
type: "auth_event",
139+
"http.client_ip": clientIp,
113140
});
114141

115142
// Fetch user details from Clerk API
@@ -126,6 +153,7 @@ export const authMiddleware = async (c: Context, next: Next) => {
126153
logger.error("[AUTH] Cannot create user - no email found in Clerk", {
127154
userId: userData.id,
128155
type: "auth_error",
156+
"http.client_ip": clientIp,
129157
});
130158
throw new HTTPException(500, {
131159
message: "User profile incomplete - email required",
@@ -160,6 +188,7 @@ export const authMiddleware = async (c: Context, next: Next) => {
160188
email: newUser.email,
161189
type: "auth_event",
162190
event_type: "user_created",
191+
"http.client_ip": clientIp,
163192
});
164193

165194
existingUser = newUser;
@@ -169,6 +198,7 @@ export const authMiddleware = async (c: Context, next: Next) => {
169198
logger.error("[AUTH] User not found in Clerk", {
170199
userId: userData.id,
171200
type: "auth_error",
201+
"http.client_ip": clientIp,
172202
});
173203
throw new HTTPException(401, {
174204
message: "User account not found",
@@ -190,6 +220,7 @@ export const authMiddleware = async (c: Context, next: Next) => {
190220
logger.error("[AUTH] User not found after race condition", {
191221
userId: userData.id,
192222
type: "database_error",
223+
"http.client_ip": clientIp,
193224
});
194225
throw new HTTPException(500, {
195226
message: "Failed to create or find user profile",
@@ -202,6 +233,7 @@ export const authMiddleware = async (c: Context, next: Next) => {
202233
userId: userData.id,
203234
error: lookupError instanceof Error ? lookupError.message : String(lookupError),
204235
type: "database_error",
236+
"http.client_ip": clientIp,
205237
},
206238
lookupError instanceof Error ? lookupError : undefined
207239
);
@@ -215,6 +247,7 @@ export const authMiddleware = async (c: Context, next: Next) => {
215247
{
216248
userId: userData.id,
217249
error: error instanceof Error ? error.message : String(error),
250+
"http.client_ip": clientIp,
218251
},
219252
error instanceof Error ? error : undefined
220253
);
@@ -235,6 +268,7 @@ export const authMiddleware = async (c: Context, next: Next) => {
235268
event_type: "auth_success",
236269
"user.id": userData.id,
237270
"user.email": existingUser.email,
271+
"http.client_ip": clientIp,
238272
});
239273

240274
// User context available in Hono context

0 commit comments

Comments
 (0)