2025-08-21 15:24:40 +09:00
|
|
|
import { Injectable } from "@nestjs/common";
|
|
|
|
|
import { ThrottlerGuard } from "@nestjs/throttler";
|
2025-09-25 13:21:11 +09:00
|
|
|
import { createHash } from "crypto";
|
2025-08-23 18:02:05 +09:00
|
|
|
import type { Request } from "express";
|
2025-08-20 18:02:50 +09:00
|
|
|
|
|
|
|
|
@Injectable()
|
|
|
|
|
export class AuthThrottleGuard extends ThrottlerGuard {
|
2025-09-19 17:37:46 +09:00
|
|
|
protected override async getTracker(req: Request): Promise<string> {
|
|
|
|
|
// Track by IP address + User Agent for better security on sensitive auth operations
|
2025-08-22 17:02:49 +09:00
|
|
|
const forwarded = req.headers["x-forwarded-for"];
|
|
|
|
|
const forwardedIp = Array.isArray(forwarded) ? forwarded[0] : forwarded;
|
2025-08-21 15:24:40 +09:00
|
|
|
const ip =
|
2025-08-23 18:02:05 +09:00
|
|
|
(typeof forwardedIp === "string" ? forwardedIp.split(",")[0]?.trim() : undefined) ||
|
2025-08-22 17:02:49 +09:00
|
|
|
(req.headers["x-real-ip"] as string | undefined) ||
|
2025-08-27 10:54:05 +09:00
|
|
|
req.socket?.remoteAddress ||
|
|
|
|
|
req.ip ||
|
2025-08-21 15:24:40 +09:00
|
|
|
"unknown";
|
|
|
|
|
|
2025-09-19 17:37:46 +09:00
|
|
|
const userAgent = req.headers["user-agent"] || "unknown";
|
2025-09-25 13:21:11 +09:00
|
|
|
const userAgentHash = createHash("sha256").update(userAgent).digest("hex").slice(0, 16);
|
2025-09-19 17:37:46 +09:00
|
|
|
|
2025-09-25 13:21:11 +09:00
|
|
|
const normalizedIp = ip.replace(/^::ffff:/, "");
|
|
|
|
|
|
|
|
|
|
const resolvedIp = await Promise.resolve(normalizedIp);
|
2025-09-19 17:37:46 +09:00
|
|
|
return `auth_${resolvedIp}_${userAgentHash}`;
|
2025-08-20 18:02:50 +09:00
|
|
|
}
|
|
|
|
|
}
|