Add new parameter 'user_info_endpoint_url' to keycload_oidc

This patch adds the possibility to specify the endpoind which will be
used for autorization. Default value is
'/realms/%s/protocol/openid-connect/userinfo' where %s is a realm name,
that will be substituded in the middleware code.
The whole url is a concatenation of 'auth_url' and 'user_info_endpoint_url'
config parameters.

Change-Id: I769b1cb8102654e341a2bf4739c787622167267f
This commit is contained in:
Mike Fedosin
2017-04-27 14:28:06 +03:00
parent acf175d335
commit d761e199a8
2 changed files with 29 additions and 7 deletions

View File

@@ -29,8 +29,14 @@ LOG = logging.getLogger(__name__)
keycloak_oidc_opts = [
cfg.StrOpt(
'auth_url',
default='http://127.0.0.1:8080/auth',
help='Keycloak base url (e.g. https://my.keycloak:8443/auth)'
),
cfg.StrOpt(
'user_info_endpoint_url',
default='/realms/%s/protocol/openid-connect/userinfo',
help='Endpoint against which authorization will be performed'
),
cfg.StrOpt(
'insecure',
default=False,
@@ -62,19 +68,15 @@ class KeycloakAuthMiddleware(base_middleware.Middleware):
self.mcclient = memcache.Client(mcserv_url) if mcserv_url else None
def authenticate(self, access_token, realm_name):
user_info_endpoint = (
"%s/realms/%s/protocol/openid-connect/userinfo" %
(CONF.keycloak_oidc.auth_url, realm_name)
)
info = None
if self.mcclient:
info = self.mcclient.get(access_token)
if info is None:
if info is None and CONF.keycloak_oidc.user_info_endpoint_url:
try:
resp = requests.get(
user_info_endpoint,
CONF.keycloak_oidc.auth_url +
(CONF.keycloak_oidc.user_info_endpoint_url % realm_name),
headers={"Authorization": "Bearer %s" % access_token},
verify=not CONF.keycloak_oidc.insecure
)

View File

@@ -50,6 +50,7 @@ class TestKeycloakAuthMiddleware(base.BaseTestCase):
self.assertEqual("Confirmed", req.headers["X-Identity-Status"])
self.assertEqual("my_realm", req.headers["X-Project-Id"])
self.assertEqual("role1,role2", req.headers["X-Roles"])
self.assertEqual(1, mocked_get.call_count)
def test_no_auth_token(self):
req = webob.Request.blank("/")
@@ -116,3 +117,22 @@ class TestKeycloakAuthMiddleware(base.BaseTestCase):
with mock.patch("jwt.decode", return_value=token):
self.assertRaises(
exc.GlareException, self._build_middleware(), req)
@mock.patch("requests.get")
def test_userinfo_endpoint_empty(self, mocked_get):
self.config(user_info_endpoint_url='',
group='keycloak_oidc')
token = {
"iss": "http://localhost:8080/auth/realms/my_realm",
"realm_access": {
"roles": ["role1", "role2"]
}
}
req = self._build_request(token)
with mock.patch("jwt.decode", return_value=token):
self._build_middleware()(req)
self.assertEqual("Confirmed", req.headers["X-Identity-Status"])
self.assertEqual("my_realm", req.headers["X-Project-Id"])
self.assertEqual("role1,role2", req.headers["X-Roles"])
self.assertEqual(0, mocked_get.call_count)