# Limit login of a specific users from whitelist IP address

**URL:** <https://forum.keycloak.org/t/limit-login-of-a-specific-users-from-whitelist-ip-address/11089>\
**Category:** Getting advice\
**Tags:** authentication\
**Created:** [September 21, 2021, 4:38am UTC](https://forum.keycloak.org/t/limit-login-of-a-specific-users-from-whitelist-ip-address/11089 "2021-09-21T04:38:42Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![truongnh](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/truongnh/32/2481_2.png) [@truongnh](https://forum.keycloak.org/u/truongnh)\
**Post date:** [September 21, 2021, 4:38am UTC](https://forum.keycloak.org/t/limit-login-of-a-specific-users-from-whitelist-ip-address/11089/1 "2021-09-21T04:38:42Z")

</div>

Hi there,

My Keycloak system has many users from different companies and the mass market.  
For example, users which have email domains `@company-x.com`, `@apple.com`, `@gmail.com`,…

The base-URL account console is public on the Internet. So all users in the realm can log in to the account console from anywhere.

> [https://my-keycloak.com/auth/realms/myrealm/account/](https://my-keycloak.com/auth/realms/myrealm/account/) (\*)

But one day, the **company-x** want their employees (users have email domain @company-x.com) can only log in to the URL (\*) from the whitelist IP address of their company’s network.

Could you give me the solution or some advice, please.

Thank you so much.

---

<div class="post-metadata">

**Author:** ![xgp](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/xgp/32/2589_2.png) [@xgp](https://forum.keycloak.org/u/xgp)\
**Post date:** [September 21, 2021, 2:59pm UTC](https://forum.keycloak.org/t/limit-login-of-a-specific-users-from-whitelist-ip-address/11089/2 "2021-09-21T14:59:11Z")

</div>

Take a look at the Authentication SPI [Server Developer Guide](https://www.keycloak.org/docs/latest/server_development/#_auth_spi)  
You can build a custom Authenticator that blocks users for a given domain for IPs that are not in a configured set.

---

<div class="post-metadata">

**Author:** ![truongnh](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/truongnh/32/2481_2.png) [@truongnh](https://forum.keycloak.org/u/truongnh)\
**Post date:** [September 22, 2021, 4:57pm UTC](https://forum.keycloak.org/t/limit-login-of-a-specific-users-from-whitelist-ip-address/11089/3 "2021-09-22T16:57:45Z")

</div>

Thank you for your reply!  
How can I capture the public IP address user log into the “account console”?  
I’m looking forward to hearing from you. Once again, thank you.

---

<div class="post-metadata">

**Author:** ![xgp](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/xgp/32/2589_2.png) [@xgp](https://forum.keycloak.org/u/xgp)\
**Post date:** [September 22, 2021, 6:00pm UTC](https://forum.keycloak.org/t/limit-login-of-a-specific-users-from-whitelist-ip-address/11089/4 "2021-09-22T18:00:23Z")

</div>

I’m not sure I understand. Where do you want to capture the IP? In your Authenticator code?

---

<div class="post-metadata">

**Author:** ![truongnh](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/truongnh/32/2481_2.png) [@truongnh](https://forum.keycloak.org/u/truongnh)\
**Post date:** [September 22, 2021, 6:12pm UTC](https://forum.keycloak.org/t/limit-login-of-a-specific-users-from-whitelist-ip-address/11089/5 "2021-09-22T18:12:23Z")

</div>

I mean:  
The base-URL account console is public on the Internet. So all users in the realm can log in to the account console from anywhere.

> [https://my-keycloak.com/auth/realms/myrealm/account/](https://my-keycloak.com/auth/realms/myrealm/account/) (\*)

The **company-x** want their employees (users have email domain @company-x.com) can only log in to the URL (\*) from the whitelist IP address of their company’s network. When they back home or go to other locations (with different public IP addresses), they will no longer be able to log in.

---

<div class="post-metadata">

**Author:** ![xgp](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/xgp/32/2589_2.png) [@xgp](https://forum.keycloak.org/u/xgp)\
**Post date:** [September 22, 2021, 6:21pm UTC](https://forum.keycloak.org/t/limit-login-of-a-specific-users-from-whitelist-ip-address/11089/6 "2021-09-22T18:21:51Z")

</div>

If you are trying to do that in a custom Authenticator you can use the `AuthenticationFlowContext`. Depending if you’re using a reverse proxy the IP can come from one of the following methods:

```auto
    // no reverse proxy
    authenticationFlowContext.getHttpRequest().getRemoteAddress();

    // with reverse proxy
    authenticationFlowContext.getHttpRequest().getHttpHeaders().getHeaderString("X-Forwarded-For");

```

---

<div class="post-metadata">

**Author:** ![PhanDuy0407](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/phanduy0407/32/3147_2.png) [@PhanDuy0407](https://forum.keycloak.org/u/PhanDuy0407)\
**Post date:** [September 23, 2021, 3:02pm UTC](https://forum.keycloak.org/t/limit-login-of-a-specific-users-from-whitelist-ip-address/11089/8 "2021-09-23T15:02:23Z")

</div>

Hi, I and @truongnh are in the same team, and I have some questions.  
When I’m using the below code

> [@xgp](#):
>
> `authenticationFlowContext.getHttpRequest().getRemoteAddress();`

the getRemoteAddress() method didn’t exist.  
Is there another way to get user’s IP when they login while I’m not using a reverse proxy ?

---

<div class="post-metadata">

**Author:** ![xgp](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/xgp/32/2589_2.png) [@xgp](https://forum.keycloak.org/u/xgp)\
**Post date:** [September 23, 2021, 3:17pm UTC](https://forum.keycloak.org/t/limit-login-of-a-specific-users-from-whitelist-ip-address/11089/9 "2021-09-23T15:17:59Z")

</div>

Sorry, I was looking at the wrong Javadoc for Resteasy. It looks like `getRemoteAddress()` isn’t there until version 4. I’d enumerate all of the headers from `getHttpHeaders()` and see if any of them contain the IP when you’re not using a reverse proxy.

---

<div class="post-metadata">

**Author:** ![xgp](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/xgp/32/2589_2.png) [@xgp](https://forum.keycloak.org/u/xgp)\
**Post date:** [September 23, 2021, 3:21pm UTC](https://forum.keycloak.org/t/limit-login-of-a-specific-users-from-whitelist-ip-address/11089/10 "2021-09-23T15:21:08Z")

</div>

Also, it looks like they get it from the session in some of the Keycloak code:

```auto
KeycloakSession session...
KeycloakContext context = session.getContext();
String ipAddress = context.getConnection().getRemoteAddr();

```

---

<div class="post-metadata">

**Author:** ![PhanDuy0407](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/phanduy0407/32/3147_2.png) [@PhanDuy0407](https://forum.keycloak.org/u/PhanDuy0407)\
**Post date:** [September 24, 2021, 12:02pm UTC](https://forum.keycloak.org/t/limit-login-of-a-specific-users-from-whitelist-ip-address/11089/11 "2021-09-24T12:02:33Z")

</div>

I’ve tried this

> [@](#):
>
> ```auto
> KeycloakSession session...
> KeycloakContext context = session.getContext();
> String ipAddress = context.getConnection().getRemoteAddr();
> 
> ```

but it only return keycloak server’s IP.

---

<div class="post-metadata">

**Author:** ![xgp](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/xgp/32/2589_2.png) [@xgp](https://forum.keycloak.org/u/xgp)\
**Post date:** [September 24, 2021, 12:29pm UTC](https://forum.keycloak.org/t/limit-login-of-a-specific-users-from-whitelist-ip-address/11089/12 "2021-09-24T12:29:11Z")

</div>

Are you running in docker or behind a reverse proxy? I just tested standalone and it works fine.

---

<div class="post-metadata">

**Author:** ![PhanDuy0407](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/phanduy0407/32/3147_2.png) [@PhanDuy0407](https://forum.keycloak.org/u/PhanDuy0407)\
**Post date:** [September 24, 2021, 1:51pm UTC](https://forum.keycloak.org/t/limit-login-of-a-specific-users-from-whitelist-ip-address/11089/13 "2021-09-24T13:51:07Z")

</div>

We’re running Keycloak on a K8s cluster with no reverse proxy.  
I’ve tested standalone too, and it returned 127.0.0.1 which is localhost.  
So when I test on a K8s cluster, using keycloak for single sign on from one of my website, it return an IP like 172.x.x.x, which is local IP of worker node running Keycloak on K8s cluster.  
The problem is we want to get user’s public IP when user login to Keycloak. Is that posible ?

---

<div class="post-metadata">

**Author:** ![xgp](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/xgp/32/2589_2.png) [@xgp](https://forum.keycloak.org/u/xgp)\
**Post date:** [September 24, 2021, 1:55pm UTC](https://forum.keycloak.org/t/limit-login-of-a-specific-users-from-whitelist-ip-address/11089/14 "2021-09-24T13:55:22Z")

</div>

This my be a k8s thing. What is the value of `authenticationFlowContext.getHttpRequest().getHttpHeaders().getHeaderString("X-Forwarded-For")`? Same?

---

<div class="post-metadata">

**Author:** ![PhanDuy0407](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/phanduy0407/32/3147_2.png) [@PhanDuy0407](https://forum.keycloak.org/u/PhanDuy0407)\
**Post date:** [September 24, 2021, 3:25pm UTC](https://forum.keycloak.org/t/limit-login-of-a-specific-users-from-whitelist-ip-address/11089/15 "2021-09-24T15:25:40Z")

</div>

When using

```auto
authenticationFlowContext.getHttpRequest().getHttpHeaders().getHeaderString("X-Forwarded-For")

```

I got 10.233.105.0 which is the IP address of Keycloak pod.

---

<div class="post-metadata">

**Author:** ![xgp](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/xgp/32/2589_2.png) [@xgp](https://forum.keycloak.org/u/xgp)\
**Post date:** [September 24, 2021, 3:32pm UTC](https://forum.keycloak.org/t/limit-login-of-a-specific-users-from-whitelist-ip-address/11089/16 "2021-09-24T15:32:17Z")

</div>

I’m afraid I can’t reproduce this. Can I ask where you are issuing the request from?

---

<div class="post-metadata">

**Author:** ![truongnh](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/truongnh/32/2481_2.png) [@truongnh](https://forum.keycloak.org/u/truongnh)\
**Post date:** [September 28, 2021, 3:28am UTC](https://forum.keycloak.org/t/limit-login-of-a-specific-users-from-whitelist-ip-address/11089/17 "2021-09-28T03:28:39Z")

</div>

Hi @xgp, thank you for your kindness.

When we implemented the following method in our custom Authenticator

> [@](#):
>
> ```java
> authenticationFlowContext.getHttpRequest().getHttpHeaders().getHeaderString("X-Forwarded-For");
> 
> ```

We could retrieve the Public IP of Clients in logs of **Ingress Nginx Controller**.  
But, when we checked logs on Keycloak pods, we only got the private IP of LoadBalancer.

Could you give us some advice, please.

---

<div class="post-metadata">

**Author:** ![xgp](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/xgp/32/2589_2.png) [@xgp](https://forum.keycloak.org/u/xgp)\
**Post date:** [September 28, 2021, 5:56am UTC](https://forum.keycloak.org/t/limit-login-of-a-specific-users-from-whitelist-ip-address/11089/18 "2021-09-28T05:56:16Z")

</div>

I’m not familiar with ingress-nginx, but you need to make sure it properly sets the “X-Forwarded-For” header to the public IP of the client before sending the request to Keycloak

---

<div class="post-metadata">

**Author:** ![jcabrera](https://avatars.discourse-cdn.com/v4/letter/j/b9e5f3/32.png) [@jcabrera](https://forum.keycloak.org/u/jcabrera)\
**Post date:** [October 8, 2021, 5:18pm UTC](https://forum.keycloak.org/t/limit-login-of-a-specific-users-from-whitelist-ip-address/11089/19 "2021-10-08T17:18:08Z")

</div>

I had this same issue when using Keycloak in Docker Swarm. I don’t have any experience with K8s but maybe this might help.

For us, there were two parts. The docker ingress network uses IPVS and SNAT which masquerades the source IP as the docker node’s ingress IP, so we would see the private IP of the docker nodes on the ingress network instead of the true source IP of the client. We have a workaround in place using the [docker-ingress-routing-daemon](https://github.com/newsnowlabs/docker-ingress-routing-daemon) as it seems to just be built this way by design in Docker Swarm.

The other part was that for our container, we needed to ensure the following environment variable was set:  
PROXY\_ADDRESS\_FORWARDING: “true”

With these two changes, we were able to see the true source IP address of the client.

From there we added IP restrictions using the undertow subsystem on certain paths so that, for example, our master realm was only accessible from our internal IPs. This can be done through the jboss cli located by default in the container at /opt/jboss/keycloak/bin/jboss-cli.sh. For us, we do this with JBoss CLI and extend the Keycloak Image because we do other customizing, but if you didn’t want to extend the keycloak image, I suppose you could just create a script that edits the standalone.xml file and just mount it at in the startup-scripts directory. Here’s a link explaining how this is done: [keycloak-documentation/admin.adoc at master · keycloak/keycloak-documentation · GitHub](https://github.com/keycloak/keycloak-documentation/blob/master/server_admin/topics/threat/admin.adoc)

I know it’s not K8s but I hope this helps!

edit: added links
