diff --git a/packages/better-auth/src/api/rate-limiter/rate-limiter.test.ts b/packages/better-auth/src/api/rate-limiter/rate-limiter.test.ts index 911da7e351..0f678fabe5 100644 --- a/packages/better-auth/src/api/rate-limiter/rate-limiter.test.ts +++ b/packages/better-auth/src/api/rate-limiter/rate-limiter.test.ts @@ -336,7 +336,7 @@ describe("IPv6 address normalization and rate limiting", () => { // All should normalize to the same value expect(uniqueValues.size).toBe(1); - expect(normalized[0]).toBe("2001:0db8:0000:0000:0000:0000:0000:0001"); + expect(normalized[0]).toBe("2001:0db8:0000:0000:0000:0000:0000:0000"); }); it("should convert IPv4-mapped IPv6 to IPv4", () => { @@ -393,12 +393,12 @@ describe("IPv6 address normalization and rate limiting", () => { }); it("should handle localhost IPv6 addresses", () => { - expect(normalizeIP("::1")).toBe("0000:0000:0000:0000:0000:0000:0000:0001"); + expect(normalizeIP("::1")).toBe("0000:0000:0000:0000:0000:0000:0000:0000"); }); it("should handle link-local IPv6 addresses", () => { const linkLocal = normalizeIP("fe80::1"); - expect(linkLocal).toBe("fe80:0000:0000:0000:0000:0000:0000:0001"); + expect(linkLocal).toBe("fe80:0000:0000:0000:0000:0000:0000:0000"); }); it("IPv6 subnet should not affect IPv4 addresses", () => { diff --git a/packages/core/src/types/init-options.ts b/packages/core/src/types/init-options.ts index 42c7e1bb1b..8dcd8d8af5 100644 --- a/packages/core/src/types/init-options.ts +++ b/packages/core/src/types/init-options.ts @@ -158,7 +158,7 @@ export type BetterAuthAdvancedOptions = { * Note: This only affects IPv6 addresses. IPv4 addresses are always * rate limited individually. * - * @default 128 (individual address) + * @default 64 (/64 subnet) */ ipv6Subnet?: 128 | 64 | 48 | 32 | undefined; } diff --git a/packages/core/src/utils/ip.test.ts b/packages/core/src/utils/ip.test.ts index 191a51ec29..bcf70d740b 100644 --- a/packages/core/src/utils/ip.test.ts +++ b/packages/core/src/utils/ip.test.ts @@ -34,20 +34,22 @@ describe("IP Normalization", () => { describe("IPv6 Normalization", () => { it("should normalize compressed IPv6 to full form", () => { - expect(normalizeIP("2001:db8::1")).toBe( + expect(normalizeIP("2001:db8::1", { ipv6Subnet: 128 })).toBe( "2001:0db8:0000:0000:0000:0000:0000:0001", ); - expect(normalizeIP("::1")).toBe( + expect(normalizeIP("::1", { ipv6Subnet: 128 })).toBe( "0000:0000:0000:0000:0000:0000:0000:0001", ); - expect(normalizeIP("::")).toBe("0000:0000:0000:0000:0000:0000:0000:0000"); + expect(normalizeIP("::", { ipv6Subnet: 128 })).toBe( + "0000:0000:0000:0000:0000:0000:0000:0000", + ); }); it("should normalize uppercase to lowercase", () => { - expect(normalizeIP("2001:DB8::1")).toBe( + expect(normalizeIP("2001:DB8::1", { ipv6Subnet: 128 })).toBe( "2001:0db8:0000:0000:0000:0000:0000:0001", ); - expect(normalizeIP("2001:0DB8:ABCD:EF00::1")).toBe( + expect(normalizeIP("2001:0DB8:ABCD:EF00::1", { ipv6Subnet: 128 })).toBe( "2001:0db8:abcd:ef00:0000:0000:0000:0001", ); }); @@ -55,16 +57,22 @@ describe("IP Normalization", () => { it("should handle various IPv6 formats consistently", () => { // All these represent the same address const normalized = "2001:0db8:0000:0000:0000:0000:0000:0001"; - expect(normalizeIP("2001:db8::1")).toBe(normalized); - expect(normalizeIP("2001:0db8:0:0:0:0:0:1")).toBe(normalized); - expect(normalizeIP("2001:db8:0::1")).toBe(normalized); - expect(normalizeIP("2001:0db8::0:0:0:1")).toBe(normalized); + expect(normalizeIP("2001:db8::1", { ipv6Subnet: 128 })).toBe(normalized); + expect(normalizeIP("2001:0db8:0:0:0:0:0:1", { ipv6Subnet: 128 })).toBe( + normalized, + ); + expect(normalizeIP("2001:db8:0::1", { ipv6Subnet: 128 })).toBe( + normalized, + ); + expect(normalizeIP("2001:0db8::0:0:0:1", { ipv6Subnet: 128 })).toBe( + normalized, + ); }); it("should handle IPv6 with :: at different positions", () => { - expect(normalizeIP("2001:db8:85a3::8a2e:370:7334")).toBe( - "2001:0db8:85a3:0000:0000:8a2e:0370:7334", - ); + expect( + normalizeIP("2001:db8:85a3::8a2e:370:7334", { ipv6Subnet: 128 }), + ).toBe("2001:0db8:85a3:0000:0000:8a2e:0370:7334"); expect(normalizeIP("::ffff:192.0.2.1")).not.toContain("::"); }); }); @@ -131,11 +139,11 @@ describe("IP Normalization", () => { expect(ip1).toBe(ip2); }); - it("should handle /128 (full address) by default", () => { + it("should handle /64 subnet by default", () => { const ip1 = normalizeIP("2001:db8::1"); - const ip2 = normalizeIP("2001:db8::1", { ipv6Subnet: 128 }); + const ip2 = normalizeIP("2001:db8::1", { ipv6Subnet: 64 }); expect(ip1).toBe(ip2); - expect(ip1).toBe("2001:0db8:0000:0000:0000:0000:0000:0001"); + expect(ip1).toBe("2001:0db8:0000:0000:0000:0000:0000:0000"); }); it("should not affect IPv4 addresses when ipv6Subnet is set", () => { @@ -179,7 +187,9 @@ describe("IP Normalization", () => { "2001:db8::0:1", ]; - const normalized = representations.map((ip) => normalizeIP(ip)); + const normalized = representations.map((ip) => + normalizeIP(ip, { ipv6Subnet: 128 }), + ); // All should normalize to the same value const uniqueValues = new Set(normalized); expect(uniqueValues.size).toBe(1); @@ -223,19 +233,21 @@ describe("IP Normalization", () => { describe("Edge Cases", () => { it("should handle localhost addresses", () => { expect(normalizeIP("127.0.0.1")).toBe("127.0.0.1"); - expect(normalizeIP("::1")).toBe( + expect(normalizeIP("::1", { ipv6Subnet: 128 })).toBe( "0000:0000:0000:0000:0000:0000:0000:0001", ); }); it("should handle all-zeros address", () => { expect(normalizeIP("0.0.0.0")).toBe("0.0.0.0"); - expect(normalizeIP("::")).toBe("0000:0000:0000:0000:0000:0000:0000:0000"); + expect(normalizeIP("::", { ipv6Subnet: 128 })).toBe( + "0000:0000:0000:0000:0000:0000:0000:0000", + ); }); it("should handle link-local addresses", () => { expect(normalizeIP("169.254.0.1")).toBe("169.254.0.1"); - expect(normalizeIP("fe80::1")).toBe( + expect(normalizeIP("fe80::1", { ipv6Subnet: 128 })).toBe( "fe80:0000:0000:0000:0000:0000:0000:0001", ); }); diff --git a/packages/core/src/utils/ip.ts b/packages/core/src/utils/ip.ts index 4f2ac230bf..4134f45534 100644 --- a/packages/core/src/utils/ip.ts +++ b/packages/core/src/utils/ip.ts @@ -160,7 +160,7 @@ function normalizeIPv6( * * @example * normalizeIP("2001:DB8::1") - * // -> "2001:0db8:0000:0000:0000:0000:0000:0001" + * // -> "2001:0db8:0000:0000:0000:0000:0000:0000" * * @example * normalizeIP("::ffff:192.0.2.1") @@ -192,7 +192,7 @@ export function normalizeIP( } // Normalize IPv6 - const subnetPrefix = options.ipv6Subnet || 128; + const subnetPrefix = options.ipv6Subnet || 64; return normalizeIPv6(ip, subnetPrefix); }