diff --git a/invenio.cfg b/invenio.cfg index 621227f..47ca1b0 100644 --- a/invenio.cfg +++ b/invenio.cfg @@ -194,7 +194,14 @@ SECURITY_SEND_REGISTER_EMAIL = False # ------------------- # See https://github.com/inveniosoftware/invenio-oauthclient/blob/master/invenio_oauthclient/config.py from invenio_oauthclient.contrib.keycloak import KeycloakSettingsHelper -from cds_rdm.oidc import cern_info_serializer, confirm_registration_form +from cds_rdm.oidc import ( + cern_info_serializer, + confirm_registration_form, + cern_group_serializer, + cern_group_handler, + cern_disconnect_handler, +) +from urllib.parse import quote _keycloak_helper = KeycloakSettingsHelper( title="CERN", @@ -202,6 +209,9 @@ _keycloak_helper = KeycloakSettingsHelper( base_url=os.environ.get("CERN_KEYCLOAK_BASE_URL", "https://keycloak-qa.cern.ch/"), realm="cern", app_key="CERN_APP_CREDENTIALS", + logout_url="https://auth.cern.ch/auth/realms/cern/protocol/openid-connect/logout?redirect_uri={}".format( + quote(SITE_UI_URL) + ), ) OAUTHCLIENT_CERN_REALM_URL = _keycloak_helper.realm_url OAUTHCLIENT_CERN_USER_INFO_URL = _keycloak_helper.user_info_url @@ -211,15 +221,23 @@ OAUTHCLIENT_CERN_USER_INFO_FROM_ENDPOINT = False handlers = _keycloak_helper.get_handlers() handlers["signup_handler"]["info_serializer"] = cern_info_serializer -rest_handlers = _keycloak_helper.get_handlers() -rest_handlers["signup_handler"]["info_serializer"] = cern_info_serializer +handlers["signup_handler"]["groups_serializer"] = cern_group_serializer +handlers["signup_handler"]["groups"] = cern_group_handler +rest_handlers = _keycloak_helper.get_rest_handlers() +handlers["signup_handler"]["info_serializer"] = cern_info_serializer +rest_handlers["signup_handler"]["groups_serializer"] = cern_group_serializer +rest_handlers["signup_handler"]["groups"] = cern_group_handler OAUTHCLIENT_SIGNUP_FORM = confirm_registration_form +_remote_app_name = "cern" + OAUTHCLIENT_REMOTE_APPS = { - "cern": _keycloak_helper.remote_app, + _remote_app_name: _keycloak_helper.remote_app, } +SECURITY_POST_LOGOUT_VIEW = "/oauth/{}/logout".format(_remote_app_name) + CERN_APP_CREDENTIALS = { "consumer_key": "CHANGE ME", "consumer_secret": "CHANGE ME", diff --git a/site/cds_rdm/oidc.py b/site/cds_rdm/oidc.py index 6ba8f8d..3bab869 100644 --- a/site/cds_rdm/oidc.py +++ b/site/cds_rdm/oidc.py @@ -3,21 +3,43 @@ from invenio_userprofiles.forms import confirm_register_form_preferences_factory from flask import current_app from werkzeug.local import LocalProxy +from invenio_oauthclient import current_oauthclient +from invenio_oauthclient.contrib.keycloak.handlers import get_user_info _security = LocalProxy(lambda: current_app.extensions["security"]) def confirm_registration_form(*args, **kwargs): Form = confirm_register_form_preferences_factory(_security.confirm_register_form) + class _Form(Form): password = None recaptcha = None submit = None # defined in the template + return _Form(*args, **kwargs) -def cern_info_serializer(remote, resp, token_user_info, user_info): +def cern_group_serializer(remote, groups, **kwargs): + """Serialize the groups response object.""" + serialized_groups = [] + # E-groups do have unique names and this name cannot be updated, therefore the name can act as an ID for invenio + for group_name in groups: + serialized_groups.append({"id": group_name, "name": group_name}) + + return serialized_groups + +def cern_group_handler(remote, resp, user): + """Retrieves groups from remote account.""" + token_user_info, user_info = get_user_info(remote, resp) + groups = token_user_info.get("groups", []) + handlers = current_oauthclient.signup_handlers[remote.name] + # `remote` param automatically injected via `make_handler` helper + return handlers["groups_serializer"](groups) + + +def cern_info_serializer(remote, resp, token_user_info, user_info): user_info = user_info or {} # prevent errors when accessing None.get(...) email = token_user_info.get("email") or user_info["email"] @@ -43,4 +65,3 @@ def cern_info_serializer(remote, resp, token_user_info, user_info): "external_id": cern_upn, "external_method": remote.name, } -