docs(security): add IP address header configuration for Better Auth

This commit is contained in:
Bereket Engida
2025-04-12 21:26:58 +03:00
parent 78f18d1f93
commit de0aadb37f
2 changed files with 42 additions and 14 deletions

View File

@@ -46,6 +46,26 @@ Plugins can also set custom cookie options to align with specific security needs
Better Auth includes built-in rate limiting to safeguard against brute-force attacks. Rate limits are applied across all routes by default, with specific routes subject to stricter limits based on potential risk.
## IP Address Headers
Better Auth uses client IP addresses for rate limiting and security monitoring. By default, it reads the IP address from the standard `X-Forwarded-For` header. However, you can configure a specific trusted header to ensure accurate IP address detection and prevent IP spoofing attacks.
You can configure the IP address header in your Better Auth configuration:
```typescript
{
security: {
ipAddress: {
ipAddressHeaders: ['cf-connecting-ip'] // or any other custom header
}
}
}
```
This ensures that Better Auth only accepts IP addresses from your trusted proxy's header, making it more difficult for attackers to bypass rate limiting or other IP-based security measures by spoofing headers.
> **Important**: When setting a custom IP address header, ensure that your proxy or load balancer is properly configured to set this header, and that it cannot be set by end users directly.
## Trusted Origins
Trusted origins prevent CSRF attacks and block open redirects. You can set a list of trusted origins in the `trustedOrigins` configuration option. Requests from origins not on this list are automatically blocked.

View File

@@ -12,25 +12,33 @@ export function getIp(
if (isTest) {
return testIP;
}
const ipHeaders = options.advanced?.ipAddress?.ipAddressHeaders;
const keys = ipHeaders || [
"x-client-ip",
"x-forwarded-for",
"cf-connecting-ip",
"fastly-client-ip",
"x-real-ip",
"x-cluster-client-ip",
"x-forwarded",
"forwarded-for",
"forwarded",
];
const headers = "headers" in req ? req.headers : req;
for (const key of keys) {
const defaultHeaders = ["x-forwarded-for"];
const ipHeaders =
options.advanced?.ipAddress?.ipAddressHeaders || defaultHeaders;
for (const key of ipHeaders) {
const value = "get" in headers ? headers.get(key) : headers[key];
if (typeof value === "string") {
const ip = value.split(",")[0].trim();
if (ip) return ip;
if (isValidIP(ip)) {
return ip;
}
}
}
return null;
}
function isValidIP(ip: string): boolean {
const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/;
if (ipv4Regex.test(ip)) {
const parts = ip.split(".").map(Number);
return parts.every((part) => part >= 0 && part <= 255);
}
const ipv6Regex = /^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/;
return ipv6Regex.test(ip);
}