Fix IP address not being set on sessions from localhost
The extractClientIP() function only checked proxy headers (X-Forwarded-For, CF-Connecting-IP, etc.) which don't exist when running locally without a proxy. Changes: - Add clientIP field to APIContext - Use Bun's server.requestIP() to get client IP from direct socket connection - Update getGeoInfo() to accept fallback IP parameter - Pass context.clientIP to getGeoInfo() in auth procedures Now sessions will have IP address set even for local development (::1 or 127.0.0.1). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -21,6 +21,8 @@ export interface APIContext {
|
|||||||
reqHeaders: Headers;
|
reqHeaders: Headers;
|
||||||
/** Response headers (for setting cookies) */
|
/** Response headers (for setting cookies) */
|
||||||
resHeaders: Headers;
|
resHeaders: Headers;
|
||||||
|
/** Client IP address from direct connection (fallback when no proxy headers) */
|
||||||
|
clientIP?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ const rpName = Bun.env.RP_NAME ?? DEFAULT_RP_NAME;
|
|||||||
|
|
||||||
Bun.serve({
|
Bun.serve({
|
||||||
port,
|
port,
|
||||||
async fetch(request) {
|
async fetch(request, server) {
|
||||||
const url = new URL(request.url);
|
const url = new URL(request.url);
|
||||||
|
|
||||||
if (url.pathname.startsWith("/api/v1/rpc")) {
|
if (url.pathname.startsWith("/api/v1/rpc")) {
|
||||||
@@ -50,6 +50,10 @@ Bun.serve({
|
|||||||
// Create response headers for setting cookies
|
// Create response headers for setting cookies
|
||||||
const resHeaders = new Headers();
|
const resHeaders = new Headers();
|
||||||
|
|
||||||
|
// Get client IP from Bun's server (fallback for when no proxy headers)
|
||||||
|
const socketInfo = server.requestIP(request);
|
||||||
|
const clientIP = socketInfo?.address ?? null;
|
||||||
|
|
||||||
const context: APIContext = {
|
const context: APIContext = {
|
||||||
db,
|
db,
|
||||||
origin,
|
origin,
|
||||||
@@ -57,6 +61,7 @@ Bun.serve({
|
|||||||
rpName,
|
rpName,
|
||||||
reqHeaders: request.headers,
|
reqHeaders: request.headers,
|
||||||
resHeaders,
|
resHeaders,
|
||||||
|
clientIP,
|
||||||
};
|
};
|
||||||
|
|
||||||
const { response } = await handler.handle(request, {
|
const { response } = await handler.handle(request, {
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ export const createLoginRequest = os.auth.createLoginRequest.handler(
|
|||||||
const hasPassword = user.password_hash !== null;
|
const hasPassword = user.password_hash !== null;
|
||||||
|
|
||||||
// Get geo info and user agent
|
// Get geo info and user agent
|
||||||
const geo = getGeoInfo(context.reqHeaders);
|
const geo = getGeoInfo(context.reqHeaders, context.clientIP);
|
||||||
const userAgent = getUserAgent(context.reqHeaders);
|
const userAgent = getUserAgent(context.reqHeaders);
|
||||||
|
|
||||||
// Create login request with secure token
|
// Create login request with secure token
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ export const loginIfRequestIsCompleted =
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get current request info
|
// Get current request info
|
||||||
const geo = getGeoInfo(context.reqHeaders);
|
const geo = getGeoInfo(context.reqHeaders, context.clientIP);
|
||||||
const userAgent = getUserAgent(context.reqHeaders);
|
const userAgent = getUserAgent(context.reqHeaders);
|
||||||
|
|
||||||
// Upsert user device
|
// Upsert user device
|
||||||
|
|||||||
@@ -225,7 +225,7 @@ export const signup = os.auth.signup.handler(async ({ input, context }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get geo info and user agent for session creation
|
// Get geo info and user agent for session creation
|
||||||
const geo = getGeoInfo(context.reqHeaders);
|
const geo = getGeoInfo(context.reqHeaders, context.clientIP);
|
||||||
const userAgent = getUserAgent(context.reqHeaders);
|
const userAgent = getUserAgent(context.reqHeaders);
|
||||||
|
|
||||||
let userId: number;
|
let userId: number;
|
||||||
|
|||||||
@@ -126,9 +126,16 @@ export const lookupGeoFromIP = (
|
|||||||
/**
|
/**
|
||||||
* Extract geolocation info from request headers.
|
* Extract geolocation info from request headers.
|
||||||
* Uses Cloudflare headers when available, falls back to GeoIP database lookup.
|
* Uses Cloudflare headers when available, falls back to GeoIP database lookup.
|
||||||
|
*
|
||||||
|
* @param headers - Request headers to extract proxy IP headers from
|
||||||
|
* @param fallbackIP - Optional fallback IP from direct socket connection (e.g., from Bun's server.requestIP)
|
||||||
*/
|
*/
|
||||||
export const getGeoInfo = (headers: Headers): GeoInfo => {
|
export const getGeoInfo = (
|
||||||
const ip = extractClientIP(headers);
|
headers: Headers,
|
||||||
|
fallbackIP?: string | null,
|
||||||
|
): GeoInfo => {
|
||||||
|
// Try proxy headers first, then fall back to direct connection IP
|
||||||
|
const ip = extractClientIP(headers) ?? fallbackIP ?? null;
|
||||||
|
|
||||||
// Try Cloudflare geo headers first
|
// Try Cloudflare geo headers first
|
||||||
const cfCountry = headers.get("CF-IPCountry");
|
const cfCountry = headers.get("CF-IPCountry");
|
||||||
|
|||||||
Reference in New Issue
Block a user