marcospereirampj / python-keycloak

MIT License
722 stars 301 forks source link

Timeout with Proxy in KeycloakOpenID #603

Open SteEcker opened 2 weeks ago

SteEcker commented 2 weeks ago

Hi, thank you for this package!

Describe the issue
I am trying to use the KeycloakOpenID client in Python to connect to a Keycloak server behind a proxy, specifying a custom certificate for SSL verification, but I encounter a timeout when the client attempts to retrieve the .well-known/openid-configuration endpoint for my realm. The direct connection to the base Keycloak URL works successfully using the requests library, but the well_known() method in the KeycloakOpenID client times out when trying to access the OpenID configuration.

Direct Request Test (Success)

When I use the requests package directly with the same proxy and certificate settings, I can successfully reach the Keycloak server:

proxies = {
    "http": "http://<proxy-url>",
    "https": "https://<proxy-url>"
}

response = requests.get(
    "https://<keycloak-server-url>",
    proxies=proxies,
    verify="/path/to/my/certificate.pem"
)
print(response.status_code)  

So I can confirm that my proxy settings are correct.

However, when I attempt to use the KeycloakOpenID client with the same proxy and certificate settings, the connection to the /.well-known/openid-configuration endpoint fails due to a timeout:

keycloak_openid = KeycloakOpenID(
    server_url="https://<keycloak-server-url>",
    client_id="<client-id>",
    realm_name="<realm-name>",
    client_secret_key="<client-secret>",
    proxies={
        "http://": "http://<proxy-url>",
        "https://": "https://<proxy-url>"
    },
    verify="/path/to/my/certificate.pem",  # Path to my certificate
)

config_well_known = keycloak_openid.well_known()  # Timeout occurs here

Logs:

DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): <keycloak-server-url>:443
DEBUG:urllib3.connectionpool:https://<keycloak-server-url>:443 "GET / HTTP/1.1" 200 3522
INFO:root:Successfully reached Keycloak server: https://<keycloak-server-url> with status code 200.
INFO:root:Initialized keycloak object
INFO:root:Getting server info
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): <keycloak-server-url>:443
WARNING:urllib3.connectionpool:Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ConnectTimeoutError': /realms/<realm-name>/.well-known/openid-configuration

Is the proxy configuration that I am passing into the KeycloakOpenID client correct?

Environment
Python version: 3.11.6 python-keycloak==4.5.1

SteEcker commented 2 weeks ago

Follow-up: Potential Issue Identified with Proxy Argument in connection.py

Hi again,

I did some digging and identified the potential root cause of the issue with the KeycloakOpenID client timing out when connecting through a proxy.

In the connection.py file, the relevant line:

self.async_s = httpx.AsyncClient(verify=verify, proxies=proxies, cert=cert)

passes the proxies argument to the httpx.AsyncClient. However, upon reviewing the httpx.AsyncClient class, I noticed that the proxies argument has been deprecated and should be replaced with the proxy argument. Here’s the key part from the documentation:

class AsyncClient(BaseClient):
<...>
if proxies:
    message = (
        "The 'proxies' argument is now deprecated."
        " Use 'proxy' or 'mounts' instead."
    )
    warnings.warn(message, DeprecationWarning)

This means that using proxies as it's currently done in the ConnectionManager class triggers this deprecation warning and might be causing the timeout issue.

I changed the client call to

self.async_s = httpx.AsyncClient(verify=verify, proxy=proxies["http"], cert=cert)

After making this change, the client successfully connects 🎉