fix request ip port strip issue with badger >=1.3.0

This commit is contained in:
miloschwartz
2025-12-22 12:35:40 -05:00
parent 89a7e2e4dc
commit 71386d3b05

View File

@@ -13,7 +13,8 @@ import {
LoginPage, LoginPage,
Org, Org,
Resource, Resource,
ResourceHeaderAuth, ResourceHeaderAuthExtendedCompatibility, ResourceHeaderAuth,
ResourceHeaderAuthExtendedCompatibility,
ResourcePassword, ResourcePassword,
ResourcePincode, ResourcePincode,
ResourceRule, ResourceRule,
@@ -39,6 +40,8 @@ import {
} from "#dynamic/lib/checkOrgAccessPolicy"; } from "#dynamic/lib/checkOrgAccessPolicy";
import { logRequestAudit } from "./logRequestAudit"; import { logRequestAudit } from "./logRequestAudit";
import cache from "@server/lib/cache"; import cache from "@server/lib/cache";
import semver from "semver";
import { APP_VERSION } from "@server/lib/consts";
const verifyResourceSessionSchema = z.object({ const verifyResourceSessionSchema = z.object({
sessions: z.record(z.string(), z.string()).optional(), sessions: z.record(z.string(), z.string()).optional(),
@@ -50,7 +53,8 @@ const verifyResourceSessionSchema = z.object({
path: z.string(), path: z.string(),
method: z.string(), method: z.string(),
tls: z.boolean(), tls: z.boolean(),
requestIp: z.string().optional() requestIp: z.string().optional(),
badgerVersion: z.string().optional()
}); });
export type VerifyResourceSessionSchema = z.infer< export type VerifyResourceSessionSchema = z.infer<
@@ -69,6 +73,7 @@ export type VerifyUserResponse = {
headerAuthChallenged?: boolean; headerAuthChallenged?: boolean;
redirectUrl?: string; redirectUrl?: string;
userData?: BasicUserData; userData?: BasicUserData;
pangolinVersion?: string;
}; };
export async function verifyResourceSession( export async function verifyResourceSession(
@@ -97,7 +102,8 @@ export async function verifyResourceSession(
requestIp, requestIp,
path, path,
headers, headers,
query query,
badgerVersion
} = parsedBody.data; } = parsedBody.data;
// Extract HTTP Basic Auth credentials if present // Extract HTTP Basic Auth credentials if present
@@ -105,7 +111,15 @@ export async function verifyResourceSession(
const clientIp = requestIp const clientIp = requestIp
? (() => { ? (() => {
logger.debug("Request IP:", { requestIp }); const isNewerBadger =
badgerVersion &&
semver.valid(badgerVersion) &&
semver.gte(badgerVersion, "1.3.1");
if (isNewerBadger) {
return requestIp;
}
if (requestIp.startsWith("[") && requestIp.includes("]")) { if (requestIp.startsWith("[") && requestIp.includes("]")) {
// if brackets are found, extract the IPv6 address from between the brackets // if brackets are found, extract the IPv6 address from between the brackets
const ipv6Match = requestIp.match(/\[(.*?)\]/); const ipv6Match = requestIp.match(/\[(.*?)\]/);
@@ -114,12 +128,17 @@ export async function verifyResourceSession(
} }
} }
// ivp4 // Check if it looks like IPv4 (contains dots and matches IPv4 pattern)
// split at last colon // IPv4 format: x.x.x.x where x is 0-255
const lastColonIndex = requestIp.lastIndexOf(":"); const ipv4Pattern = /^(\d{1,3}\.){3}\d{1,3}/;
if (lastColonIndex !== -1) { if (ipv4Pattern.test(requestIp)) {
return requestIp.substring(0, lastColonIndex); const lastColonIndex = requestIp.lastIndexOf(":");
if (lastColonIndex !== -1) {
return requestIp.substring(0, lastColonIndex);
}
} }
// Return as is
return requestIp; return requestIp;
})() })()
: undefined; : undefined;
@@ -130,9 +149,7 @@ export async function verifyResourceSession(
? await getCountryCodeFromIp(clientIp) ? await getCountryCodeFromIp(clientIp)
: undefined; : undefined;
const ipAsn = clientIp const ipAsn = clientIp ? await getAsnFromIp(clientIp) : undefined;
? await getAsnFromIp(clientIp)
: undefined;
let cleanHost = host; let cleanHost = host;
// if the host ends with :port, strip it // if the host ends with :port, strip it
@@ -178,7 +195,13 @@ export async function verifyResourceSession(
cache.set(resourceCacheKey, resourceData, 5); cache.set(resourceCacheKey, resourceData, 5);
} }
const { resource, pincode, password, headerAuth, headerAuthExtendedCompatibility } = resourceData; const {
resource,
pincode,
password,
headerAuth,
headerAuthExtendedCompatibility
} = resourceData;
if (!resource) { if (!resource) {
logger.debug(`Resource not found ${cleanHost}`); logger.debug(`Resource not found ${cleanHost}`);
@@ -474,8 +497,7 @@ export async function verifyResourceSession(
return notAllowed(res); return notAllowed(res);
} }
} } else if (headerAuth) {
else if (headerAuth) {
// if there are no other auth methods we need to return unauthorized if nothing is provided // if there are no other auth methods we need to return unauthorized if nothing is provided
if ( if (
!sso && !sso &&
@@ -713,7 +735,11 @@ export async function verifyResourceSession(
} }
// If headerAuthExtendedCompatibility is activated but no clientHeaderAuth provided, force client to challenge // If headerAuthExtendedCompatibility is activated but no clientHeaderAuth provided, force client to challenge
if (headerAuthExtendedCompatibility && headerAuthExtendedCompatibility.extendedCompatibilityIsActivated && !clientHeaderAuth){ if (
headerAuthExtendedCompatibility &&
headerAuthExtendedCompatibility.extendedCompatibilityIsActivated &&
!clientHeaderAuth
) {
return headerAuthChallenged(res, redirectPath, resource.orgId); return headerAuthChallenged(res, redirectPath, resource.orgId);
} }
@@ -825,7 +851,7 @@ async function notAllowed(
} }
const data = { const data = {
data: { valid: false, redirectUrl }, data: { valid: false, redirectUrl, pangolinVersion: APP_VERSION },
success: true, success: true,
error: false, error: false,
message: "Access denied", message: "Access denied",
@@ -839,8 +865,8 @@ function allowed(res: Response, userData?: BasicUserData) {
const data = { const data = {
data: data:
userData !== undefined && userData !== null userData !== undefined && userData !== null
? { valid: true, ...userData } ? { valid: true, ...userData, pangolinVersion: APP_VERSION }
: { valid: true }, : { valid: true, pangolinVersion: APP_VERSION },
success: true, success: true,
error: false, error: false,
message: "Access allowed", message: "Access allowed",
@@ -879,7 +905,12 @@ async function headerAuthChallenged(
} }
const data = { const data = {
data: { headerAuthChallenged: true, valid: false, redirectUrl }, data: {
headerAuthChallenged: true,
valid: false,
redirectUrl,
pangolinVersion: APP_VERSION
},
success: true, success: true,
error: false, error: false,
message: "Access denied", message: "Access denied",