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:
@@ -29,8 +29,14 @@ LOG = logging.getLogger(__name__)
|
|||||||
keycloak_oidc_opts = [
|
keycloak_oidc_opts = [
|
||||||
cfg.StrOpt(
|
cfg.StrOpt(
|
||||||
'auth_url',
|
'auth_url',
|
||||||
|
default='http://127.0.0.1:8080/auth',
|
||||||
help='Keycloak base url (e.g. https://my.keycloak:8443/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(
|
cfg.StrOpt(
|
||||||
'insecure',
|
'insecure',
|
||||||
default=False,
|
default=False,
|
||||||
@@ -62,19 +68,15 @@ class KeycloakAuthMiddleware(base_middleware.Middleware):
|
|||||||
self.mcclient = memcache.Client(mcserv_url) if mcserv_url else None
|
self.mcclient = memcache.Client(mcserv_url) if mcserv_url else None
|
||||||
|
|
||||||
def authenticate(self, access_token, realm_name):
|
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
|
info = None
|
||||||
if self.mcclient:
|
if self.mcclient:
|
||||||
info = self.mcclient.get(access_token)
|
info = self.mcclient.get(access_token)
|
||||||
|
|
||||||
if info is None:
|
if info is None and CONF.keycloak_oidc.user_info_endpoint_url:
|
||||||
try:
|
try:
|
||||||
resp = requests.get(
|
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},
|
headers={"Authorization": "Bearer %s" % access_token},
|
||||||
verify=not CONF.keycloak_oidc.insecure
|
verify=not CONF.keycloak_oidc.insecure
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ class TestKeycloakAuthMiddleware(base.BaseTestCase):
|
|||||||
self.assertEqual("Confirmed", req.headers["X-Identity-Status"])
|
self.assertEqual("Confirmed", req.headers["X-Identity-Status"])
|
||||||
self.assertEqual("my_realm", req.headers["X-Project-Id"])
|
self.assertEqual("my_realm", req.headers["X-Project-Id"])
|
||||||
self.assertEqual("role1,role2", req.headers["X-Roles"])
|
self.assertEqual("role1,role2", req.headers["X-Roles"])
|
||||||
|
self.assertEqual(1, mocked_get.call_count)
|
||||||
|
|
||||||
def test_no_auth_token(self):
|
def test_no_auth_token(self):
|
||||||
req = webob.Request.blank("/")
|
req = webob.Request.blank("/")
|
||||||
@@ -116,3 +117,22 @@ class TestKeycloakAuthMiddleware(base.BaseTestCase):
|
|||||||
with mock.patch("jwt.decode", return_value=token):
|
with mock.patch("jwt.decode", return_value=token):
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exc.GlareException, self._build_middleware(), req)
|
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)
|
||||||
|
|||||||
Reference in New Issue
Block a user