Skip to content

Commit cef60e8

Browse files
Get IP address IN Keycloak
1 parent 247844f commit cef60e8

1 file changed

Lines changed: 31 additions & 3 deletions

File tree

src/auth/auth.service.ts

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,38 @@ export class AuthService {
2626
private readonly keycloakService: KeycloakService
2727
) {}
2828

29+
private getClientIpForKeycloak(request: Request): string | undefined {
30+
const ipFromExpress = normalizeIpForForwarding(request?.ip);
31+
if (ipFromExpress) return ipFromExpress;
32+
33+
// Fallback: only trust X-Forwarded-For if the direct connection is internal (proxy hop).
34+
const remoteAddress = normalizeIpForForwarding(request?.socket?.remoteAddress);
35+
const isInternal =
36+
!!remoteAddress &&
37+
(remoteAddress === '127.0.0.1' ||
38+
remoteAddress === '::1' ||
39+
remoteAddress.startsWith('10.') ||
40+
remoteAddress.startsWith('192.168.') ||
41+
(remoteAddress.startsWith('172.') &&
42+
(() => {
43+
const second = parseInt(remoteAddress.slice(4, 7), 10);
44+
return second >= 16 && second <= 31;
45+
})()));
46+
47+
if (!isInternal) return undefined;
48+
49+
const xff = request?.headers?.['x-forwarded-for'];
50+
const raw =
51+
typeof xff === 'string' ? xff : Array.isArray(xff) ? xff.join(',') : undefined;
52+
if (!raw) return undefined;
53+
const first = raw.split(',')[0]?.trim();
54+
return normalizeIpForForwarding(first);
55+
}
56+
2957
async login(request: Request, authDto, response: Response) {
3058
const apiId = APIID.LOGIN;
3159
const { username, password } = authDto;
32-
const clientIp = normalizeIpForForwarding(request?.ip);
60+
const clientIp = this.getClientIpForKeycloak(request);
3361

3462
try {
3563
// Optimized: Only check user status (no tenant/role data needed for login)
@@ -126,7 +154,7 @@ export class AuthService {
126154
response: Response
127155
): Promise<LoginResponse> {
128156
const apiId = APIID.REFRESH;
129-
const clientIp = normalizeIpForForwarding(request?.ip);
157+
const clientIp = this.getClientIpForKeycloak(request);
130158
const { access_token, expires_in, refresh_token, refresh_expires_in } =
131159
await this.keycloakService.refreshToken(refreshToken, clientIp).catch(() => {
132160
throw new UnauthorizedException();
@@ -149,7 +177,7 @@ export class AuthService {
149177

150178
async logout(request: Request, refreshToken: string, response: Response) {
151179
const apiId = APIID.LOGOUT;
152-
const clientIp = normalizeIpForForwarding(request?.ip);
180+
const clientIp = this.getClientIpForKeycloak(request);
153181
try {
154182
const logout = await this.keycloakService.logout(refreshToken, clientIp);
155183
return APIResponse.success(

0 commit comments

Comments
 (0)