diff --git a/swh/auth/keycloak.py b/swh/auth/keycloak.py
index 72d243ce2535e8591825710ab9d431c33c5358cc..4d72d63d10d2015e16e3f0e24f966b56912ff369 100644
--- a/swh/auth/keycloak.py
+++ b/swh/auth/keycloak.py
@@ -8,6 +8,8 @@ from urllib.parse import urlencode
 
 from keycloak import KeycloakOpenID
 
+from swh.core.config import load_from_envvar
+
 
 class KeycloakOpenIDConnect:
     """
@@ -158,3 +160,43 @@ class KeycloakOpenIDConnect:
             A dictionary fillled with user information
         """
         return self._keycloak.userinfo(access_token)
+
+    @classmethod
+    def from_config(cls, **kwargs: Any) -> "KeycloakOpenIDConnect":
+        """Instantiate a KeycloakOpenIDConnect class from a configuration dict.
+
+        Args:
+
+            kwargs: configuration dict for the instance, with one keycloak key, whose
+                value is a Dict with the following keys:
+                - server_url: URL of the Keycloak server
+                - realm_name: The realm name
+                - client_id: The OpenID Connect client identifier
+
+        Returns:
+            the KeycloakOpenIDConnect instance
+
+        """
+        cfg = kwargs["keycloak"]
+        return cls(
+            server_url=cfg["server_url"],
+            realm_name=cfg["realm_name"],
+            client_id=cfg["client_id"],
+        )
+
+    @classmethod
+    def from_configfile(cls, **kwargs: Any) -> "KeycloakOpenIDConnect":
+
+        """Instantiate a KeycloakOpenIDConnect class from the configuration loaded from the
+        SWH_CONFIG_FILENAME envvar, with potential extra keyword arguments if their
+        value is not None.
+
+        Args:
+            kwargs: kwargs passed to instantiation call
+
+        Returns:
+            the KeycloakOpenIDConnect instance
+        """
+        config = dict(load_from_envvar()).get("keycloak", {})
+        config.update({k: v for k, v in kwargs.items() if v is not None})
+        return cls.from_config(keycloak=config)
diff --git a/swh/auth/tests/test_keycloak.py b/swh/auth/tests/test_keycloak.py
index 5cf774e2433c9665cd6c7e68750749d217c37fc6..3bcda9f4b8806bf3385b22df79d2649ce8833c8e 100644
--- a/swh/auth/tests/test_keycloak.py
+++ b/swh/auth/tests/test_keycloak.py
@@ -4,11 +4,14 @@
 # See top-level LICENSE file for more information
 
 from copy import copy
+import os
 from urllib.parse import parse_qs, urlparse
 
 from keycloak.exceptions import KeycloakError
 import pytest
+import yaml
 
+from swh.auth.keycloak import KeycloakOpenIDConnect
 from swh.auth.pytest_plugin import keycloak_mock_factory
 from swh.auth.tests.sample_data import (
     CLIENT_ID,
@@ -18,6 +21,7 @@ from swh.auth.tests.sample_data import (
     SERVER_URL,
     USER_INFO,
 )
+from swh.core.config import read
 
 # Make keycloak fixture to use for tests below.
 keycloak_mock = keycloak_mock_factory(
@@ -98,3 +102,63 @@ def test_keycloak_decode_token(keycloak_mock):
 def test_keycloak_login(keycloak_mock):
     actual_response = keycloak_mock.login("username", "password")
     assert actual_response == OIDC_PROFILE
+
+
+@pytest.fixture
+def auth_config():
+    return {
+        "keycloak": {
+            "server_url": "https://auth.swh.org/SWHTest",
+            "realm_name": "SWHTest",
+            "client_id": "client_id",
+        }
+    }
+
+
+@pytest.fixture
+def auth_config_path(tmp_path, monkeypatch, auth_config):
+    conf_path = os.path.join(tmp_path, "auth.yml")
+    with open(conf_path, "w") as f:
+        f.write(yaml.dump(auth_config))
+    monkeypatch.setenv("SWH_CONFIG_FILENAME", conf_path)
+    return conf_path
+
+
+def test_auth_KeycloakOpenIDConnect_from_config(auth_config):
+    """Instantiating keycloak client out of configuration dict is possible
+
+     """
+    client = KeycloakOpenIDConnect.from_config(**auth_config)
+
+    assert client.server_url == auth_config["keycloak"]["server_url"]
+    assert client.realm_name == auth_config["keycloak"]["realm_name"]
+    assert client.client_id == auth_config["keycloak"]["client_id"]
+
+
+def test_auth_KeycloakOpenIDConnect_from_configfile(auth_config_path, monkeypatch):
+    """Instantiating keycloak client out of environment variable is possible
+
+     """
+    client = KeycloakOpenIDConnect.from_configfile()
+
+    auth_config = read(auth_config_path)
+
+    assert client.server_url == auth_config["keycloak"]["server_url"]
+    assert client.realm_name == auth_config["keycloak"]["realm_name"]
+    assert client.client_id == auth_config["keycloak"]["client_id"]
+
+
+def test_auth_KeycloakOpenIDConnect_from_configfile_override(
+    auth_config_path, monkeypatch
+):
+    """Instantiating keycloak client out of environment variable is possible
+    And caller can override the configuration  at calling
+
+     """
+    client = KeycloakOpenIDConnect.from_configfile(client_id="foobar")
+
+    auth_config = read(auth_config_path)
+
+    assert client.server_url == auth_config["keycloak"]["server_url"]
+    assert client.realm_name == auth_config["keycloak"]["realm_name"]
+    assert client.client_id == "foobar"