From 83931d3722f86168bebf39aca5ca2055e6f176aa Mon Sep 17 00:00:00 2001 From: Dominik Frantisek Bucik <bucik@ics.muni.cz> Date: Thu, 6 Jun 2024 18:56:26 +0200 Subject: [PATCH] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20Great=20refactor=20o?= =?UTF-8?q?f=20redirects?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit USe session attributes for passing data across redirects to have safe passing mechanism --- .../localization/messages_cs.properties | 40 ++- .../localization/messages_en.properties | 40 ++- .../src/main/webapp/WEB-INF/views/aup.jsp | 2 +- ...sTestSpWarning.jsp => test_rp_warning.jsp} | 8 +- .../{unapproved.jsp => unauthorized.jsp} | 2 +- ....jsp => unauthorized_ensure_vo_member.jsp} | 23 +- ...ized_ensure_vo_member_notify_redirect.jsp} | 20 +- .../views/unauthorized_is_eligible.jsp | 49 +++ .../views/unauthorized_not_in_env_units.jsp | 51 +++ ...unauthorized_register_choose_vo_group.jsp} | 26 +- ...orized_register_notify_action_required.jsp | 51 +++ ...pproved_spec.jsp => unauthorized_spec.jsp} | 2 +- .../src/main/webapp/WEB-INF/web-context.xml | 25 +- ... unauthorized_register_choose_vo_group.js} | 12 +- .../java/cz/muni/ics/oidc/PerunConstants.java | 2 + .../java/cz/muni/ics/oidc/RedirectUtils.java | 45 +++ .../server/adapters/PerunAdapterMethods.java | 24 +- .../adapters/PerunAdapterMethodsRpc.java | 7 + .../adapters/impl/PerunAdapterImpl.java | 24 +- .../adapters/impl/PerunAdapterLdap.java | 89 +++-- .../server/adapters/impl/PerunAdapterRpc.java | 123 +++++-- .../EntitlementExtendedClaimSource.java | 5 +- .../claims/sources/EntitlementSource.java | 5 +- .../claims/sources/GroupNamesSource.java | 7 +- .../server/connectors/PerunConnectorRpc.java | 2 + .../ics/oidc/server/filters/FiltersUtils.java | 107 +----- .../server/filters/impl/IsEligibleFilter.java | 63 ++-- .../impl/PerunAuthorizationFilter.java | 121 ++++++- .../filters/impl/PerunEnsureVoMember.java | 89 +++-- .../filters/impl/PerunIsTestSpFilter.java | 27 +- .../filters/impl/PerunLogIdentityFilter.java | 9 +- .../filters/impl/ProxyStatisticsFilter.java | 2 +- .../server/filters/impl/ValidUserFilter.java | 81 +++-- .../oidc/web/controllers/AupController.java | 25 +- .../oidc/web/controllers/ControllerUtils.java | 87 +++-- .../web/controllers/IsTestSpController.java | 65 ---- .../oidc/web/controllers/LoginController.java | 3 - .../PerunUnapprovedController.java | 255 -------------- ...PerunUnapprovedRegistrationController.java | 176 ---------- .../PerunUnauthorizedController.java | 324 ++++++++++++++++++ .../controllers/RegistrationController.java | 42 --- .../controllers/TestSpWarningController.java | 63 ++++ 42 files changed, 1199 insertions(+), 1024 deletions(-) rename perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/{isTestSpWarning.jsp => test_rp_warning.jsp} (76%) rename perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/{unapproved.jsp => unauthorized.jsp} (96%) rename perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/{unapproved_is_eligible.jsp => unauthorized_ensure_vo_member.jsp} (56%) rename perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/{registrationFormContinue.jsp => unauthorized_ensure_vo_member_notify_redirect.jsp} (66%) create mode 100644 perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized_is_eligible.jsp create mode 100644 perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized_not_in_env_units.jsp rename perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/{registrationForm.jsp => unauthorized_register_choose_vo_group.jsp} (70%) create mode 100644 perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized_register_notify_action_required.jsp rename perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/{unapproved_spec.jsp => unauthorized_spec.jsp} (89%) rename perun-oidc-server-webapp/src/main/webapp/resources/js/{reg_form_select.js => unauthorized_register_choose_vo_group.js} (61%) create mode 100644 perun-oidc-server/src/main/java/cz/muni/ics/oidc/RedirectUtils.java delete mode 100644 perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/IsTestSpController.java delete mode 100644 perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/PerunUnapprovedController.java delete mode 100644 perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/PerunUnapprovedRegistrationController.java create mode 100644 perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/PerunUnauthorizedController.java delete mode 100644 perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/RegistrationController.java create mode 100644 perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/TestSpWarningController.java diff --git a/perun-oidc-server-webapp/src/main/resources/localization/messages_cs.properties b/perun-oidc-server-webapp/src/main/resources/localization/messages_cs.properties index d5c8744fa..0f0f2fad5 100644 --- a/perun-oidc-server-webapp/src/main/resources/localization/messages_cs.properties +++ b/perun-oidc-server-webapp/src/main/resources/localization/messages_cs.properties @@ -69,22 +69,25 @@ zoneinfo=Z\u00F3na phone_number=Telefon #UNAPPROVED -contact_p=V p\u0159\u00EDpad\u011B nejasnost\u00ED n\u00E1s kontaktujte na +403_aai_contact_text=V p\u0159\u00EDpad\u011B nejasnost\u00ED n\u00E1s kontaktujte na 403_header=P\u0159\u00EDstup odm\u00EDtnut 403_text=Nem\u00E1te dostate\u010Dn\u00E1 pr\u00E1va pro p\u0159\u00EDstup ke slu\u017Eb\u011B: 403_informationPage=Pro v\u00EDce informac\u00ED o slu\u017Eb\u011B nav\u0161tivte 403_contactSupport=Pokud si mysl\u00EDte \u017Ee m\u00E1te m\u00EDt p\u0159\u00EDstup, kontaktujte administr\u00E1tora: 403_subject=Probl\u00E9m s p\u0159ihl\u00E1\u0161en\u00EDm do slu\u017Eby + 403_ensure_vo_hdr=P\u0159\u00EDstup zam\u00EDtnut 403_ensure_vo_msg=Nem\u00E1te dostate\u010Dn\u00E1 pr\u00E1va pro p\u0159\u00EDstup ke slu\u017Eb\u011B +403_ensure_vo_client_contact=Pokud si mysl\u00EDte, \u017Ee v\u00E1m byl p\u0159\u00EDstup odep\u0159en nepr\u00E1vem, nebo chcete p\u0159\u00EDstup z\u00EDskat, kontaktujte spr\u00E1vce slu\u017Eby pomoc\u00ED kontakt\u016F n\u00ED\u017Ee. + 403_authorization_hdr=P\u0159\u00EDstup zam\u00EDtnut 403_authorization_msg=Tato str\u00E1nka se V\u00E1m zobrazuje, proto\u017Ee nem\u00E1te p\u0159\u00EDstup ke slu\u017Eb\u011B. To m\u016F\u017Ee b\u00FDt d\u016Fsledkem p\u0159\u00EDstupov\u00FDch omezen\u00ED nastaven\u00FDch administr\u00E1torem. -403_not_in_test_vos_groups_hdr=P\u0159\u00EDstup zam\u00EDtnut -403_not_in_test_vos_groups_msg=Tato str\u00E1nka se V\u00E1m zobrazuje, proto\u017Ee nem\u00E1te p\u0159\u00EDstup k testovac\u00EDm slu\u017Eb\u00E1m AAI. -403_not_in_prod_vos_groups_hdr=P\u0159\u00EDstup zam\u00EDtnut -403_not_in_prod_vos_groups_msg=Tato str\u00E1nka se V\u00E1m zobrazuje, proto\u017Ee nem\u00E1te p\u0159\u00EDstup ke slu\u017Eb\u00E1m AAI. -403_not_in_mandatory_vos_groups_hdr=P\u0159\u00EDstup zam\u00EDtnut -403_not_in_mandatory_vos_groups_msg=Tato str\u00E1nka se V\u00E1m zobrazuje, proto\u017Ee Va\u0161e po\u017Eadovan\u00E9 \u010Dlenstv\u00ED v organizaci je nevalidn\u00ED. + +403_not_in_env_vos_groups_hdr=P\u0159\u00EDstup zam\u00EDtnut +403_not_in_env_vos_groups_msg=Tato str\u00E1nka se V\u00E1m zobrazuje, proto\u017Ee nespl\u0148ujete podm\u00EDnky \u010Dlenstv\u00ED v organiza\u010Dn\u00EDch jednotk\u00E1ch AAI. +403_not_in_env_vos_groups_urls=Pomoc\u00ED n\u00E1sleduj\u00FA\u00EDc\u00EDch odkaz\u016F se m\u016F\u017Eete do organiza\u010Dn\u00EDch jednotek registrovat. Pokud nevid\u00EDte \u017E\u00E1dn\u00E9 odkazy, kontaktujte spr\u00E1ve slu\u017Eby pro p\u0159idelen\u00ED p\u0159\u00EDstupu. +403_not_in_env_vos_groups_client_contact=Pokud si mysl\u00EDte, \u017Ee v\u00E1m byl p\u0159\u00EDstup odep\u0159en nepr\u00E1vem, nebo chcete p\u0159\u00EDstup z\u00EDskat, kontaktujte spr\u00E1vce slu\u017Eby pomoc\u00ED kontakt\u016F n\u00ED\u017Ee. + 403_not_logged_in_hdr=P\u0159\u00EDstup zam\u00EDtnut 403_not_logged_in_msg=Zd\u00E1 se, \u017Ee p\u0159ihl\u00E1\u0161en\u00ED selhalo. Zkuste, pros\u00EDm, zav\u0159\u00EDt V\u00E1\u0161 prohl\u00ED\u017Ee\u010D a p\u0159ihl\u00E1sit se znovu. @@ -92,21 +95,22 @@ contact_p=V p\u0159\u00EDpad\u011B nejasnost\u00ED n\u00E1s kontaktujte na 403_is_eligible_default_text=P\u0159\u00EDstup ke slu\u017Eb\u011B byl zam\u00EDtnut, proto\u017Ee V\u00E1\u0161 \u00FA\u010Det nespl\u0148uje pomd\u00EDnky p\u0159\u00EDstupu. P\u0159ihlaste se, pros\u00EDme, pomoc\u00ED jin\u00E9ho \u00FA\u010Dtu. 403_is_eligible_default_button_text=Pokra\u010Dovat 403_is_eligible_default_contact_text=Pokud si mysl\u00EDte, \u017Ee pou\u017E\u00EDv\u00E1te spr\u00E1vn\u00FD \u00FA\u010Det a p\u0159\u00EDstup je V\u00E1m odm\u00EDtnut nepr\u00E1vem, pros\u00EDme kontakujte n\u00E1s na +403_is_eligible_client_contact=Pokud si mysl\u00EDte, \u017Ee v\u00E1m byl p\u0159\u00EDstup odep\u0159en nepr\u00E1vem, nebo chcete p\u0159\u00EDstup z\u00EDskat, kontaktujte spr\u00E1vce slu\u017Eby pomoc\u00ED kontakt\u016F n\u00ED\u017Ee. #GO TO REGISTRATION -go_to_registration_title=Je vy\u017Eadov\u00E1na Va\u0161e aktivita -go_to_registration_header1=Pro p\u0159\u00EDstup ke slu\u017Eb\u011B -go_to_registration_header2=je vy\u017Eadov\u00E1na Va\u0161e aktivita -go_to_registration_continue=Pokra\u010Dovat na str\u00E1nku s dopl\u0148uj\u00EDc\u00EDmi informacemi +unauthorized_register_notify_action_required_title=Je vy\u017Eadov\u00E1na Va\u0161e aktivita +unauthorized_register_notify_action_required_header1=Pro p\u0159\u00EDstup ke slu\u017Eb\u011B +unauthorized_register_notify_action_required_header2=je vy\u017Eadov\u00E1na Va\u0161e aktivita +unauthorized_register_notify_action_required_continue=Pokra\u010Dovat na str\u00E1nku s dopl\u0148uj\u00EDc\u00EDmi informacemi #REGISTRATION -registration_title=Registrace pro p\u0159\u00EDstup ke slu\u017Eb\u011B -registration_header1=P\u0159\u00EDstup ke slu\u017Eb\u011B -registration_header2=byl zam\u00EDtnut -registration_message=Pro z\u00EDsk\u00E1n\u00ED p\u0159\u00EDstupu k dan\u00E9 slu\u017Eb\u011B je nutn\u00E9 b\u00FDt \u010Dlenem jedn\u00E9 z n\u00E1sleduj\u00EDc\u00EDch skupin. Pokra\u010Dujte v\u00FDb\u011Brem p\u0159\u00EDslu\u0161n\u00E9 organizace a skupiny. -registration_select_vo=Vyberte virtu\u00E1ln\u00ED organizaci: -registration_select_group=Vyberte skupinu pro registraci: -registration_continue=Pokra\u010Dovat na registra\u010Dn\u00ED str\u00E1nku do vybran\u00E9 skupiny +unauthorized_register_choose_vo_group_title=Registrace pro p\u0159\u00EDstup ke slu\u017Eb\u011B +unauthorized_register_choose_vo_group_header1=P\u0159\u00EDstup ke slu\u017Eb\u011B +unauthorized_register_choose_vo_group_header2=byl zam\u00EDtnut +unauthorized_register_choose_vo_group_message=Pro z\u00EDsk\u00E1n\u00ED p\u0159\u00EDstupu k dan\u00E9 slu\u017Eb\u011B je nutn\u00E9 b\u00FDt \u010Dlenem jedn\u00E9 z n\u00E1sleduj\u00EDc\u00EDch skupin. Pokra\u010Dujte v\u00FDb\u011Brem p\u0159\u00EDslu\u0161n\u00E9 organizace a skupiny. +unauthorized_register_choose_vo_group_select_vo=Vyberte virtu\u00E1ln\u00ED organizaci: +unauthorized_register_choose_vo_group_select_group=Vyberte skupinu pro registraci: +unauthorized_register_choose_vo_group_continue=Pokra\u010Dovat na registra\u010Dn\u00ED str\u00E1nku do vybran\u00E9 skupiny #CESNET footer specific footer_other_projects=OSTATN\u00CD PROJEKTY diff --git a/perun-oidc-server-webapp/src/main/resources/localization/messages_en.properties b/perun-oidc-server-webapp/src/main/resources/localization/messages_en.properties index a51323982..4e05cdcc7 100644 --- a/perun-oidc-server-webapp/src/main/resources/localization/messages_en.properties +++ b/perun-oidc-server-webapp/src/main/resources/localization/messages_en.properties @@ -68,22 +68,25 @@ zoneinfo=Zone phone_number=Phone #UNAPPROVED -contact_p=In case of any questions, do not hesitate to contact us at +403_aai_contact_text=In case of any questions, do not hesitate to contact us at 403_header=Access forbidden 403_text=You don't meet the prerequisites for accessing the service: 403_informationPage=For more information about this service please visit this 403_contactSupport=If you think you should have an access contact service operator at 403_subject=Problem with login to service: + 403_ensure_vo_hdr=Access denied 403_ensure_vo_msg=You don't meet the prerequisites to access the service. +403_ensure_vo_client_contact=If you think you should have access to the service, you can contact the service operator via the email(s) below. + 403_authorization_hdr=Access denied 403_authorization_msg=You see this page because you are not allowed to access the service. This situation can be a result of the access restrictions that the service administrator has set up. -403_not_in_test_vos_groups_hdr=Access denied -403_not_in_test_vos_groups_msg=You see this page because you are not allowed to access AAI's testing services. -403_not_in_prod_vos_groups_hdr=Access denied -403_not_in_prod_vos_groups_msg=You see this page because you are not allowed to access AAI's services. -403_not_in_mandatory_vos_groups_hdr=Access denied -403_not_in_mandatory_vos_groups_msg=You are seeing this page because your membership in the required organizational units is invalid. + +403_not_in_env_vos_groups_hdr=Access denied +403_not_in_env_vos_groups_msg=You see this page because you are not allowed to access this service. The reason is that you are not member of the required organizational units. +403_not_in_env_vos_groups_urls=Please register into the required units using the links below. If you see no links, please get in touch with the service operator to grant you access. +403_not_in_env_vos_groups_client_contact=If you need more information about the access requirements, please use one of the contacts of the service operator below. + 403_not_logged_in_hdr=Access denied 403_not_logged_in_msg=It appears the login process has failed. Please close your browser and try to log in again. @@ -91,21 +94,22 @@ contact_p=In case of any questions, do not hesitate to contact us at 403_is_eligible_default_text=Your account does not meet the criteria for accessing the service. Please log in with other account. 403_is_eligible_default_button_text=Continue with other account. 403_is_eligible_default_contact_text=If you think you have used an account which meets the criteria, and you are still prevented from logging in to the service, please contact us at +403_is_eligible_client_contact=If you think you should have access to the service, you can contact the service operator via the email(s) below. #GO TO REGISTRATION -go_to_registration_title=Your activity is necessary -go_to_registration_header1=Your activity is necessary to access the -go_to_registration_header2=service -go_to_registration_continue=Continue to a page with additional information +unauthorized_register_notify_action_required_title=Your activity is necessary +unauthorized_register_notify_action_required_header1=Your activity is necessary to access the +unauthorized_register_notify_action_required_header2=service +unauthorized_register_notify_action_required_continue=Continue to a page with additional information #REGISTRATION -registration_title=Registration for access to the service -registration_header1=Access to the service -registration_header2=has been forbidden -registration_message=To access the service it is necessary to have a valid membership in one of the following groups. Please proceed with selection of organization and group for registration. -registration_select_vo=Select virtual organization for registration: -registration_select_group=Select group for registration: -registration_continue=Continue to the registration page for selected group +unauthorized_register_choose_vo_group_title=Registration for access to the service +unauthorized_register_choose_vo_group_header1=Access to the service +unauthorized_register_choose_vo_group_header2=has been forbidden +unauthorized_register_choose_vo_group_message=To access the service it is necessary to have a valid membership in one of the following groups. Please proceed with selection of organization and group for registration. +unauthorized_register_choose_vo_group_select_vo=Select virtual organization for registration: +unauthorized_register_choose_vo_group_select_group=Select group for registration: +unauthorized_register_choose_vo_group_continue=Continue to the registration page for selected group #CESNET+einfra footer specific footer_other_projects=OTHER CESNET PROJECTS diff --git a/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/aup.jsp b/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/aup.jsp index 3a3c54cf6..3a6caab7f 100644 --- a/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/aup.jsp +++ b/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/aup.jsp @@ -29,7 +29,7 @@ request.setAttribute("cssLinks", cssLinks); <div> <p style="font-size: 16px; padding: 0; margin: 0;"><spring:message code="org_vo"/>${" "}<strong>${aup.key}</strong></p> <p><spring:message code="see_aup"/>${" "}${aup.value.version}${" "} - <a href="${aup.value.link}"><spring:message code="here"/></a></p> + <a href="${aup.value.link}" target="_blank"><spring:message code="here"/></a></p> </div> </c:forEach> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> diff --git a/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/isTestSpWarning.jsp b/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/test_rp_warning.jsp similarity index 76% rename from perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/isTestSpWarning.jsp rename to perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/test_rp_warning.jsp index fc4be6d4d..4831f9c68 100644 --- a/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/isTestSpWarning.jsp +++ b/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/test_rp_warning.jsp @@ -27,13 +27,11 @@ </div> <p><spring:message code="is_test_sp_warning_text"/></p> - <form method="GET" action="${action}"> + <form method="POST" action=""> <hr/> <br/> - <input type="hidden" name="target" value="${fn:escapeXml(target)}"> - <input type="hidden" name="accepted" value="true"> - <spring:message code="is_test_sp_warning_continue" var="submit_value"/> - <input type="submit" name="continue" value="${submit_value}" class="btn btn-lg btn-primary btn-block"> + <input type="submit" name="continue" value="<spring:message code="is_test_sp_warning_continue"/>" + class="btn btn-lg btn-primary btn-block"> </form> </div> </div><!-- ENDWRAP --> diff --git a/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unapproved.jsp b/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized.jsp similarity index 96% rename from perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unapproved.jsp rename to perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized.jsp index 5bfda5a7c..99420eb38 100644 --- a/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unapproved.jsp +++ b/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized.jsp @@ -32,7 +32,7 @@ request.setAttribute("cssLinks", cssLinks); <c:if test="${not empty client.clientUri}"> <br/> <spring:message key="403_informationPage"/>${' '} - <a href="${fn:escapeXml(client.clientUri)}"> + <a href="${fn:escapeXml(client.clientUri)}" target="_blank"> ${fn:escapeXml(client.clientUri)} </a> </c:if> diff --git a/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unapproved_is_eligible.jsp b/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized_ensure_vo_member.jsp similarity index 56% rename from perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unapproved_is_eligible.jsp rename to perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized_ensure_vo_member.jsp index 6170db3e3..051db6d01 100644 --- a/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unapproved_is_eligible.jsp +++ b/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized_ensure_vo_member.jsp @@ -16,19 +16,26 @@ request.setAttribute("cssLinks", cssLinks); <t:header title="${title}" reqURL="${reqURL}" baseURL="${baseURL}" cssLinks="${cssLinks}" theme="${theme}" samlResourcesURL="${samlResourcesURL}"/> - </div> <%-- header --%> <div id="content"> <div class="error_message" style="word-wrap: break-word;"> - <h1><spring:message code="${outHeader}"/></h1> - <p><spring:message code="${outMessage}"/></p> - <c:if test="${hasTarget}"> - <form method="POST" action="" class="mb-4"> - <button class="btn btn-primary btn-block"><spring:message code="${outButton}"/></button> - </form> + <h1><spring:message code="403_ensure_vo_hdr"/></h1> + <p><spring:message code="403_ensure_vo_msg"/></p> + <c:if test="${not empty client and not empty client.contacts}"> + <p><spring:message code="403_ensure_vo_client_contact"/></p> + <ul> + <c:forEach items="${client.contacts}" var="contact"> + <li> + <a href="mailto:${fn:escapeXml(contact)}">${fn:escapeXml(contact)}</a> + </li> + </c:forEach> + </ul> </c:if> - <p><spring:message code="${outContactP}"/>${" "}<a href="mailto:${contactMail}">${contactMail}</a></p> + <p> + <spring:message code="403_aai_contact_text"/>${" "} + <a href="mailto:${fn:escapeXml(contactMail)}">${fn:escapeXml(contactMail)}</a> + </p> </div> </div> </div><!-- ENDWRAP --> diff --git a/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/registrationFormContinue.jsp b/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized_ensure_vo_member_notify_redirect.jsp similarity index 66% rename from perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/registrationFormContinue.jsp rename to perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized_ensure_vo_member_notify_redirect.jsp index 49ed92f2a..35c0c8833 100644 --- a/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/registrationFormContinue.jsp +++ b/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized_ensure_vo_member_notify_redirect.jsp @@ -1,25 +1,24 @@ <%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" trimDirectiveWhitespaces="true" %> <%@ page import="java.util.ArrayList" %> <%@ page import="java.util.List" %> +<%@ page import="cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> <%@ taglib prefix="t" tagdir="/WEB-INF/tags/common"%> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> - - <% String samlCssUrl = (String) request.getAttribute("samlResourcesURL"); List<String> cssLinks = new ArrayList<>(); -cssLinks.add(samlCssUrl + "/module.php/perun/res/css/perun_identity_go_to_registration.css"); +cssLinks.add(samlCssUrl + "/module.php/perun/res/css/perun_identity_unauthorized_register_notify_action_required.css"); request.setAttribute("cssLinks", cssLinks); %> -<spring:message code="go_to_registration_title" var="title"/> +<spring:message code="unauthorized_register_notify_action_required_title" var="title"/> <t:header title="${title}" reqURL="${reqURL}" baseURL="${baseURL}" cssLinks="${cssLinks}" theme="${theme}" samlResourcesURL="${samlResourcesURL}"/> @@ -27,25 +26,22 @@ request.setAttribute("cssLinks", cssLinks); <div id="content"> <div id="head"> - <h1><spring:message code="go_to_registration_header1"/> + <h1><spring:message code="unauthorized_register_notify_action_required_header1"/> <c:choose> <c:when test="${not empty client.clientName and not empty client.clientUri}"> - ${" "}<a href="${fn:escapeXml(client.uri)}">${fn:escapeXml(client.clientName)}</a> + ${" "}<a href="${fn:escapeXml(client.clientUri)}" target="_blank">${fn:escapeXml(client.clientName)}</a> </c:when> <c:when test="${not empty client.clientName}"> ${" "}${fn:escapeXml(client.clientName)} </c:when> </c:choose> - ${" "}<spring:message code="go_to_registration_header2"/> + ${" "}<spring:message code="unauthorized_register_notify_action_required_header2"/> </h1> </div> - <form method="GET" action="${action}"> + <form action="${pageContext.request.contextPath}${PerunUnauthorizedController.UNAUTHORIZED_REGISTER_CHOOSE_VO_GROUP_MAPPING}" method="GET"> <hr/> <br/> - <input type="hidden" name="client_id" value="${fn:escapeXml(client_id)}" /> - <input type="hidden" name="facility_id" value="${fn:escapeXml(facility_id)}" /> - <input type="hidden" name="user_id" value="${fn:escapeXml(user_id)}" /> - <spring:message code="go_to_registration_continue" var="submit_value"/> + <spring:message code="unauthorized_register_notify_action_required_continue" var="submit_value"/> <input type="submit" name="continueToRegistration" value="${submit_value}" class="btn btn-lg btn-primary btn-block"> </form> diff --git a/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized_is_eligible.jsp b/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized_is_eligible.jsp new file mode 100644 index 000000000..8e8cd185b --- /dev/null +++ b/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized_is_eligible.jsp @@ -0,0 +1,49 @@ +<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" trimDirectiveWhitespaces="true" %> +<%@ page import="java.util.ArrayList" %> +<%@ page import="java.util.List" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="t" tagdir="/WEB-INF/tags/common"%> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> + +<% + +List<String> cssLinks = new ArrayList<>(); + +request.setAttribute("cssLinks", cssLinks); + +%> + +<t:header title="${title}" reqURL="${reqURL}" baseURL="${baseURL}" + cssLinks="${cssLinks}" theme="${theme}" samlResourcesURL="${samlResourcesURL}"/> + +</div> <%-- header --%> + +<div id="content"> + <div class="error_message" style="word-wrap: break-word;"> + <h1><spring:message code="${outHeader}"/></h1> + <p><spring:message code="${outMessage}"/></p> + <c:if test="${not empty target}"> + <form method="GET" action="${target}" class="mb-4"> + <input class="btn btn-primary btn-block" value="<spring:message code="${outButton}"/>" type="submit"/> + </form> + </c:if> + <c:if test="${not empty client and not empty client.contacts}"> + <p><spring:message code="403_is_eligible_client_contact"/></p> + <ul> + <c:forEach items="${client.contacts}" var="contact"> + <li> + <a href="mailto:${fn:escapeXml(contact)}">${fn:escapeXml(contact)}</a> + </li> + </c:forEach> + </ul> + </c:if> + <p> + <spring:message code="${outContactP}"/>${" "} + <a href="mailto:${fn:escapeXml(contactMail)}">${fn:escapeXml(contactMail)}</a> + </p> + </div> +</div> +</div><!-- ENDWRAP --> + +<t:footer baseURL="${baseURL}" theme="${theme}" samlResourcesURL="${samlResourcesURL}"/> diff --git a/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized_not_in_env_units.jsp b/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized_not_in_env_units.jsp new file mode 100644 index 000000000..0a6997700 --- /dev/null +++ b/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized_not_in_env_units.jsp @@ -0,0 +1,51 @@ +<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" trimDirectiveWhitespaces="true" %> +<%@ page import="java.util.ArrayList" %> +<%@ page import="java.util.List" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="t" tagdir="/WEB-INF/tags/common"%> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> + +<% + +List<String> cssLinks = new ArrayList<>(); + +request.setAttribute("cssLinks", cssLinks); + +%> + +<t:header title="${title}" reqURL="${reqURL}" baseURL="${baseURL}" + cssLinks="${cssLinks}" theme="${theme}" samlResourcesURL="${samlResourcesURL}"/> +</div> <%-- header --%> + +<div id="content"> + <div class="error_message" style="word-wrap: break-word;"> + <h1><spring:message code="403_not_in_env_vos_groups_hdr"/></h1> + <p><spring:message code="403_not_in_env_vos_groups_msg"/></p> + <p><spring:message code="403_not_in_env_vos_groups_urls"/></p> + <c:if test="${not empty registrationUrls}"> + <ul> + <c:forEach var="entry" items="${registrationUrls}"> + <a href="<c:out value="${entry.key}" />" target="_blank"> + <c:out value="${entry.value}" /> + </a> + </c:forEach> + </ul> + </c:if> + <c:if test="${not empty client and not empty client.contacts}"> + <p> + <spring:message code="403_not_in_env_vos_groups_client_contact"/> + </p> + <ul> + <c:forEach items="${client.contacts}" var="contact"> + <li> + <a href="mailto:${fn:escapeXml(contact)}">${fn:escapeXml(contact)}</a> + </li> + </c:forEach> + </ul> + </c:if> + </div> +</div> +</div><!-- ENDWRAP --> + +<t:footer baseURL="${baseURL}" theme="${theme}" samlResourcesURL="${samlResourcesURL}"/> diff --git a/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/registrationForm.jsp b/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized_register_choose_vo_group.jsp similarity index 70% rename from perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/registrationForm.jsp rename to perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized_register_choose_vo_group.jsp index 34c2775a2..3fbc92efc 100644 --- a/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/registrationForm.jsp +++ b/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized_register_choose_vo_group.jsp @@ -6,8 +6,6 @@ <%@ taglib prefix="t" tagdir="/WEB-INF/tags/common"%> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> - - <% String samlCssUrl = (String) request.getAttribute("samlResourcesURL"); @@ -18,7 +16,7 @@ cssLinks.add(samlCssUrl + "/module.php/perun/res/css/perun_identity_choose_vo_an request.setAttribute("cssLinks", cssLinks); %> -<spring:message code="registration_title" var="title"/> +<spring:message code="unauthorized_register_choose_vo_group_title" var="title"/> <t:header title="${title}" reqURL="${reqURL}" baseURL="${baseURL}" cssLinks="${cssLinks}" theme="${theme}" samlResourcesURL="${samlResourcesURL}"/> @@ -26,24 +24,24 @@ request.setAttribute("cssLinks", cssLinks); <div id="content"> <div id="head"> - <h1><spring:message code="registration_header1"/> + <h1><spring:message code="unauthorized_register_choose_vo_group_header1"/> <c:choose> <c:when test="${not empty client.clientName and not empty client.clientUri}"> -  <a href="${fn:escapeXml(client.clientUri)}">${fn:escapeXml(client.clientName)}</a> +  <a href="${fn:escapeXml(client.clientUri)}" target="_blank">${fn:escapeXml(client.clientName)}</a> </c:when> <c:when test="${not empty client.clientName}">  ${fn:escapeXml(client.clientName)} </c:when> </c:choose> - ${" "}<spring:message code="registration_header2"/> + ${" "}<spring:message code="unauthorized_register_choose_vo_group_header2"/> </h1> </div> - <div class="msg"><spring:message code="registration_message"/></div> + <div class="msg"><spring:message code="unauthorized_register_choose_vo_group_message"/></div> <div class="list-group"> - <form action="${action}" method="get"> - <h4><spring:message code="registration_select_vo"/></h4> - <select id="selectVo" class="form-control" name="selectedVo" onchange="filter()" required> + <form action="${registrarUrl}" method="GET"> + <h4><spring:message code="unauthorized_register_choose_vo_group_select_vo"/></h4> + <select id="selectVo" class="form-control" onchange="filter()" required name="vo"> <c:forEach var="voGroupPair" items="${groupsForRegistration}"> <option value="${fn:escapeXml(voGroupPair.key.shortName)}"> ${fn:escapeXml(voGroupPair.key.name)} @@ -51,8 +49,8 @@ request.setAttribute("cssLinks", cssLinks); </c:forEach> </select> - <h4 class="selectGroup" style="display: none"><spring:message code="registration_select_group"/></h4> - <select class="selectGroup form-control" name="selectedGroup" class="form-control" style="display: none" required> + <h4 class="selectGroup" style="display: none"><spring:message code="unauthorized_register_choose_vo_group_select_group"/></h4> + <select class="selectGroup form-control" style="display: none" required name="group"> <c:forEach var="voGroupPair" items="${groupsForRegistration}"> <c:forEach var="group" items="${voGroupPair.value}"> <option class="groupOption" value="${fn:escapeXml(voGroupPair.key.shortName)}:${fn:escapeXml(group.name)}"> @@ -62,7 +60,7 @@ request.setAttribute("cssLinks", cssLinks); </c:forEach> </select> - <spring:message code="registration_continue" var="submit_value"/> + <spring:message code="unauthorized_register_choose_vo_group_continue" var="submit_value"/> <input type="submit" value="${submit_value}" class="btn btn-lg btn-primary btn-block"> </form> </div> @@ -71,4 +69,4 @@ request.setAttribute("cssLinks", cssLinks); <t:footer baseURL="${baseURL}" theme="${theme}" samlResourcesURL="${samlResourcesURL}"/> -<script type="text/javascript" src="resources/js/reg_form_select.js"></script> +<script type="text/javascript" src="resources/js/unauthorized_register_choose_vo_group.js"></script> diff --git a/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized_register_notify_action_required.jsp b/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized_register_notify_action_required.jsp new file mode 100644 index 000000000..35c0c8833 --- /dev/null +++ b/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized_register_notify_action_required.jsp @@ -0,0 +1,51 @@ +<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" trimDirectiveWhitespaces="true" %> +<%@ page import="java.util.ArrayList" %> +<%@ page import="java.util.List" %> +<%@ page import="cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="t" tagdir="/WEB-INF/tags/common"%> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> + +<% + +String samlCssUrl = (String) request.getAttribute("samlResourcesURL"); +List<String> cssLinks = new ArrayList<>(); + +cssLinks.add(samlCssUrl + "/module.php/perun/res/css/perun_identity_unauthorized_register_notify_action_required.css"); + +request.setAttribute("cssLinks", cssLinks); + +%> + +<spring:message code="unauthorized_register_notify_action_required_title" var="title"/> +<t:header title="${title}" reqURL="${reqURL}" baseURL="${baseURL}" + cssLinks="${cssLinks}" theme="${theme}" samlResourcesURL="${samlResourcesURL}"/> + +</div> <%-- header --%> + +<div id="content"> + <div id="head"> + <h1><spring:message code="unauthorized_register_notify_action_required_header1"/> + <c:choose> + <c:when test="${not empty client.clientName and not empty client.clientUri}"> + ${" "}<a href="${fn:escapeXml(client.clientUri)}" target="_blank">${fn:escapeXml(client.clientName)}</a> + </c:when> + <c:when test="${not empty client.clientName}"> + ${" "}${fn:escapeXml(client.clientName)} + </c:when> + </c:choose> + ${" "}<spring:message code="unauthorized_register_notify_action_required_header2"/> + </h1> + </div> + <form action="${pageContext.request.contextPath}${PerunUnauthorizedController.UNAUTHORIZED_REGISTER_CHOOSE_VO_GROUP_MAPPING}" method="GET"> + <hr/> + <br/> + <spring:message code="unauthorized_register_notify_action_required_continue" var="submit_value"/> + <input type="submit" name="continueToRegistration" value="${submit_value}" + class="btn btn-lg btn-primary btn-block"> + </form> +</div> +</div><!-- ENDWRAP --> + +<t:footer baseURL="${baseURL}" theme="${theme}" samlResourcesURL="${samlResourcesURL}"/> \ No newline at end of file diff --git a/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unapproved_spec.jsp b/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized_spec.jsp similarity index 89% rename from perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unapproved_spec.jsp rename to perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized_spec.jsp index de564e6d0..ce1130d4e 100644 --- a/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unapproved_spec.jsp +++ b/perun-oidc-server-webapp/src/main/webapp/WEB-INF/views/unauthorized_spec.jsp @@ -22,7 +22,7 @@ request.setAttribute("cssLinks", cssLinks); <div class="error_message" style="word-wrap: break-word;"> <h1><spring:message code="${outHeader}"/></h1> <p><spring:message code="${outMessage}"/></p> - <p><spring:message code="contact_p"/>${" "}<a href="mailto:${contactMail}">${contactMail}</a></p> + <p><spring:message code="403_aai_contact_text"/>${" "}<a href="mailto:${contactMail}">${contactMail}</a></p> </div> </div> </div><!-- ENDWRAP --> diff --git a/perun-oidc-server-webapp/src/main/webapp/WEB-INF/web-context.xml b/perun-oidc-server-webapp/src/main/webapp/WEB-INF/web-context.xml index b66ff2613..8cde01ada 100644 --- a/perun-oidc-server-webapp/src/main/webapp/WEB-INF/web-context.xml +++ b/perun-oidc-server-webapp/src/main/webapp/WEB-INF/web-context.xml @@ -60,21 +60,18 @@ <mvc:exclude-mapping path="/#{T(cz.muni.ics.oauth2.web.endpoint.IntrospectionEndpoint).URL}**" /> <mvc:exclude-mapping path="/#{T(cz.muni.ics.oauth2.web.endpoint.RevocationEndpoint).URL}**" /> <mvc:exclude-mapping path="/#{T(cz.muni.ics.oauth2.web.endpoint.DynamicRegistrationEndpoint).URL}**" /> - <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.IsTestSpController).MAPPING}**" /> + <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.TestSpWarningController).MAPPING}**" /> <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.AupController).URL}**" /> - <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedController).UNAPPROVED_MAPPING}**" /> - <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedController).UNAPPROVED_AUTHORIZATION}**" /> - <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedController).UNAPPROVED_ENSURE_VO_MAPPING}**" /> - <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedController).UNAPPROVED_IS_ELIGIBLE_MAPPING}**" /> - <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedController).UNAPPROVED_NOT_IN_MANDATORY_VOS_GROUPS}**" /> - <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedController).UNAPPROVED_NOT_IN_PROD_VOS_GROUPS}**" /> - <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedController).UNAPPROVED_NOT_IN_TEST_VOS_GROUPS}**" /> - <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedController).UNAPPROVED_NOT_LOGGED_IN}**" /> - <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedController).UNAPPROVED_SPECIFIC_MAPPING}**" /> - <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedRegistrationController).REGISTRATION_CONTINUE_MAPPING}**" /> - <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedRegistrationController).REGISTRATION_FORM_MAPPING}**" /> - <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedRegistrationController).REGISTRATION_FORM_SUBMIT_MAPPING}**" /> - <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.RegistrationController).CONTINUE_DIRECT_MAPPING}**" /> + <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController).UNAUTHORIZED_MAPPING}**" /> + <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController).UNAUTHORIZED_REGISTER_CHOOSE_VO_GROUP_MAPPING}**" /> + <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController).UNAUTHORIZED_AUTHORIZATION_MAPPING}**" /> + <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController).UNAUTHORIZED_ENSURE_VO_MAPPING}**" /> + <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController).UNAUTHORIZED_ENSURE_VO_REDIRECT_NOTIFY_MAPPING}**" /> + <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController).UNAUTHORIZED_IS_ELIGIBLE_MAPPING}**" /> + <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController).UNAUTHORIZED_NOT_IN_ENV_VOS_GROUPS_MAPPING}**" /> + <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController).UNAUTHORIZED_NOT_LOGGED_IN_MAPPING}**" /> + <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController).UNAUTHORIZED_REGISTER_NOTIFY_ACTION_REQUIRED_MAPPING}**" /> + <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController).UNAUTHORIZED_SPECIFIC_MAPPING}**" /> <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.LogoutController).MAPPING_SUCCESS}" /> <mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.LoginController).MAPPING_FAILURE}" /> <mvc:exclude-mapping path="/saml**" /> diff --git a/perun-oidc-server-webapp/src/main/webapp/resources/js/reg_form_select.js b/perun-oidc-server-webapp/src/main/webapp/resources/js/unauthorized_register_choose_vo_group.js similarity index 61% rename from perun-oidc-server-webapp/src/main/webapp/resources/js/reg_form_select.js rename to perun-oidc-server-webapp/src/main/webapp/resources/js/unauthorized_register_choose_vo_group.js index 86fc13cc1..f9d9a431e 100644 --- a/perun-oidc-server-webapp/src/main/webapp/resources/js/reg_form_select.js +++ b/perun-oidc-server-webapp/src/main/webapp/resources/js/unauthorized_register_choose_vo_group.js @@ -1,6 +1,8 @@ +const selectGroup = $(".selectGroup"); + function filter() { hideGroups(); - $(".selectGroup").val(""); + selectGroup.val(""); const vo = $("#selectVo").val(); if (vo !== "") { showGroups(); @@ -15,10 +17,14 @@ function filter() { } } function showGroups() { - $(".selectGroup").show(); + selectGroup.show(); + selectGroup.prop("required", true); + selectGroup.prop("disabled", false); } function hideGroups() { - $(".selectGroup").hide(); + selectGroup.hide(); + selectGroup.prop("required", false); + selectGroup.prop("disabled", true); } $(document).ready(function () { $("#selectVo").val(""); diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/PerunConstants.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/PerunConstants.java index b0463689c..128474767 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/PerunConstants.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/PerunConstants.java @@ -7,5 +7,7 @@ public interface PerunConstants { String REGISTRAR_TARGET_EXTENDED = "targetextended"; String REGISTRAR_PARAM_VO = "vo"; + String REGISTRAR_PARAM_GROUP = "group"; + String GROUP_NAME_MEMBERS = "members"; } diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/RedirectUtils.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/RedirectUtils.java new file mode 100644 index 000000000..851b5cf16 --- /dev/null +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/RedirectUtils.java @@ -0,0 +1,45 @@ +package cz.muni.ics.oidc; + +import cz.muni.ics.oidc.server.configurations.PerunOidcConfig; +import cz.muni.ics.oidc.web.controllers.ControllerUtils; +import org.springframework.http.HttpHeaders; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.util.Collections; +import java.util.Map; + +public class RedirectUtils { + + + private RedirectUtils() { + // disallow instantiation + } + public static void redirectInternal(HttpServletRequest req, + HttpServletResponse res, + PerunOidcConfig config, + String endpoint, + Map<String, Object> sessionParams) + { + String redirectUrl = ControllerUtils.createRedirectUrl(config.getBaseURL(), endpoint, Collections.emptyMap()); + + HttpSession sess = req.getSession(true); + for (Map.Entry<String, Object> entry : sessionParams.entrySet()) { + sess.setAttribute(entry.getKey(), entry.getValue()); + } + + res.reset(); + res.setStatus(HttpServletResponse.SC_FOUND); + res.setHeader(HttpHeaders.LOCATION, redirectUrl); + } + + public static void redirectExternal(HttpServletResponse res, + String location) + { + res.reset(); + res.setStatus(HttpServletResponse.SC_FOUND); + res.setHeader(HttpHeaders.LOCATION, location); + } + +} diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/PerunAdapterMethods.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/PerunAdapterMethods.java index f0120bae2..0a6e6c381 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/PerunAdapterMethods.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/PerunAdapterMethods.java @@ -314,34 +314,14 @@ public interface PerunAdapterMethods { */ Set<Long> getUserGroupsIds(Long userId, Long voId); - /** - * Check if user is valid member of given VOs (identified by IDs) - * @param userId ID of user in Perun - * @param mandatoryVos Set of IDs identifying the VOs - * @param mandatoryGroups Set of IDs identifying the Groups - * @param envVos Set of IDs identifying the VOs - * @param envGroups Set of IDs identifying the Groups - * @return returns TRUE if: - * User is member of at least one specified mandatory VO, and - * User is member of at least one specified mandatory GROUP, and - * User is member of at least one specified env VO, and - * User is member of at least one specified env GROUP. - * Returns FALSE otherwise. - */ - boolean isValidMemberInGroupsAndVos(Long userId, Set<Long> mandatoryVos, Set<Long> mandatoryGroups, - Set<Long> envVos, Set<Long> envGroups); - /** * Check if user is valid member of given VOs (identified by IDs) * @param userId ID of user in Perun * @param vos Set of IDs identifying the VOs * @param groups Set of IDs identifying the Groups - * @return returns TRUE if: - * User is member of at least one specified mandatory VO, and - * User is member of at least one specified mandatory GROUP, and - * Returns FALSE otherwise. + * @return returns set of names (vo short_names and group full qualified names) where user is not valid member */ - boolean isValidMemberInGroupsAndVos(Long userId, Set<Long> vos, Set<Long> groups); + Set<String> getVosAndGroupsNamesWhereUserInvalid(Long userId, Set<Long> vos, Set<Long> groups); boolean isUserInVo(Long userId, String voShortName); diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/PerunAdapterMethodsRpc.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/PerunAdapterMethodsRpc.java index 9dc800278..1c8ef3788 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/PerunAdapterMethodsRpc.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/PerunAdapterMethodsRpc.java @@ -11,6 +11,7 @@ import cz.muni.ics.oidc.server.connectors.Affiliation; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Set; /** * Interface with specific methods that only rpc interface can execute @@ -229,4 +230,10 @@ public interface PerunAdapterMethodsRpc { boolean hasApplicationForm(String voShortName); + /** + * Get map of Vo to Set of Groups based on unique group names + * @param invalidUnits set of strings in format vo_short_name[:g_name]* + * @return Map of VOs to Set of Groups + */ + Map<Vo, Set<Group>> getRegistrationUnits(Set<String> invalidUnits); } diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterImpl.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterImpl.java index 1160ca0d2..10a1a5f0d 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterImpl.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterImpl.java @@ -10,6 +10,8 @@ import cz.muni.ics.oidc.server.adapters.PerunAdapter; import cz.muni.ics.oidc.server.connectors.Affiliation; import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -365,28 +367,12 @@ public class PerunAdapterImpl extends PerunAdapter { } @Override - public boolean isValidMemberInGroupsAndVos(Long userId, Set<Long> mandatoryVos, Set<Long> mandatoryGroups, - Set<Long> envVos, Set<Long> envGroups) { + public Set<String> getVosAndGroupsNamesWhereUserInvalid(Long userId, Set<Long> vos, Set<Long> groups) { try { - return this.getAdapterPrimary().isValidMemberInGroupsAndVos(userId, mandatoryVos, mandatoryGroups, - envVos, envGroups); + return this.getAdapterPrimary().getVosAndGroupsNamesWhereUserInvalid(userId, vos, groups); } catch (UnsupportedOperationException e) { if (this.isCallFallback()) { - return this.getAdapterFallback().isValidMemberInGroupsAndVos(userId, mandatoryVos, mandatoryGroups, - envVos, envGroups); - } else { - throw e; - } - } - } - - @Override - public boolean isValidMemberInGroupsAndVos(Long userId, Set<Long> vos, Set<Long> groups) { - try { - return this.getAdapterPrimary().isValidMemberInGroupsAndVos(userId, vos, groups); - } catch (UnsupportedOperationException e) { - if (this.isCallFallback()) { - return this.getAdapterFallback().isValidMemberInGroupsAndVos(userId, vos, groups); + return this.getAdapterFallback().getVosAndGroupsNamesWhereUserInvalid(userId, vos, groups); } else { throw e; } diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterLdap.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterLdap.java index 6f93e3a18..e731865af 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterLdap.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterLdap.java @@ -444,8 +444,14 @@ public class PerunAdapterLdap extends PerunAdapterWithMappingServices implements } @Override - public boolean isValidMemberInGroupsAndVos(Long userId, Set<Long> mandatoryVos, Set<Long> mandatoryGroups, - Set<Long> envVos, Set<Long> envGroups) { + public Set<String> getVosAndGroupsNamesWhereUserInvalid(Long userId, Set<Long> vos, Set<Long> groups) { + if (vos == null) { + vos = new HashSet<>(); + } + if (groups == null) { + groups = new HashSet<>(); + } + final Set<Long> foundGroupIds = new HashSet<>(); final Set<Long> foundVoIds = new HashSet<>(); String dnPrefix = getDnPrefixForUserId(userId); @@ -469,35 +475,66 @@ public class PerunAdapterLdap extends PerunAdapterWithMappingServices implements }; connectorLdap.lookup(dnPrefix, attributes, mapper); - return PerunAdapter.decideAccess(foundVoIds, foundGroupIds, mandatoryVos, mandatoryGroups, envVos, envGroups); - } + Set<Long> voIdsToRegister = new HashSet<>(vos); + voIdsToRegister.removeAll(foundVoIds); - @Override - public boolean isValidMemberInGroupsAndVos(Long userId, Set<Long> vos, Set<Long> groups) { - final Set<Long> foundGroupIds = new HashSet<>(); - final Set<Long> foundVoIds = new HashSet<>(); - String dnPrefix = getDnPrefixForUserId(userId); - String[] attributes = new String[] { MEMBER_OF }; - EntryMapper<Void> mapper = e -> { - if (checkHasAttributes(e, attributes)) { - Attribute a = e.get(MEMBER_OF); - a.iterator().forEachRemaining(id -> { - String fullVal = id.getString(); - String[] parts = fullVal.split(",", 3); + Set<Long> groupIdsToRegister = new HashSet<>(groups); + groupIdsToRegister.removeAll(foundGroupIds); - String groupId = parts[0]; - groupId = groupId.replace(PERUN_GROUP_ID + '=', ""); - foundGroupIds.add(Long.parseLong(groupId)); - String voIdStr = parts[1]; - voIdStr = voIdStr.replace(PERUN_VO_ID + '=', ""); - foundVoIds.add(Long.parseLong(voIdStr)); - }); + if (voIdsToRegister.isEmpty() && groupIdsToRegister.isEmpty()) { + return new HashSet<>(); + } + + Set<String> unitNames = new HashSet<>(); + if (!voIdsToRegister.isEmpty()) { + unitNames.addAll(getVoShortNamesByVoIds(voIdsToRegister)); + } + if (!groupIdsToRegister.isEmpty()) { + unitNames.addAll(getGroupShortNamesByVoIds(groupIdsToRegister)); + } + return unitNames; + } + + private Set<String> getVoShortNamesByVoIds(Set<Long> voIds) { + String[] attributes = new String[] { O }; + List<FilterBuilder> voIdsFilter = new ArrayList<>(); + for (Long voId : voIds) { + voIdsFilter.add(equal(PERUN_VO_ID, voId.toString())); + } + FilterBuilder filter = and( + equal(OBJECT_CLASS, PERUN_VO), or(voIdsFilter.toArray(new FilterBuilder[]{})) + ); + EntryMapper<String> mapper = e -> { + if (!checkHasAttributes(e, attributes)) { + return null; } - return null; + Attribute a = e.get(attributes[0]); + return a.getString(); }; - connectorLdap.lookup(dnPrefix, attributes, mapper); + List<String> voShortNames = connectorLdap.search(null, filter, SearchScope.ONELEVEL, attributes, mapper); + voShortNames.removeIf(Objects::isNull); + return new HashSet<>(voShortNames); + } - return PerunAdapter.decideAccess(foundVoIds, foundGroupIds, vos, groups); + private Set<String> getGroupShortNamesByVoIds(Set<Long> groupIds) { + String[] attributes = new String[] { PERUN_UNIQUE_GROUP_NAME }; + List<FilterBuilder> voIdsFilter = new ArrayList<>(); + for (Long groupId : groupIds) { + voIdsFilter.add(equal(PERUN_GROUP_ID, groupId.toString())); + } + FilterBuilder filter = and( + equal(OBJECT_CLASS, PERUN_GROUP), or(voIdsFilter.toArray(new FilterBuilder[]{})) + ); + EntryMapper<String> mapper = e -> { + if (!checkHasAttributes(e, attributes)) { + return null; + } + Attribute a = e.get(attributes[0]); + return a.getString(); + }; + List<String> groupUniqueNames = connectorLdap.search(null, filter, SearchScope.SUBTREE, attributes, mapper); + groupUniqueNames.removeIf(Objects::isNull); + return new HashSet<>(groupUniqueNames); } @Override diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterRpc.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterRpc.java index 326e06ccf..0b02757b6 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterRpc.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterRpc.java @@ -2,6 +2,7 @@ package cz.muni.ics.oidc.server.adapters.impl; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.NullNode; +import cz.muni.ics.oidc.PerunConstants; import cz.muni.ics.oidc.models.AttributeMapping; import cz.muni.ics.oidc.models.Facility; import cz.muni.ics.oidc.models.Group; @@ -57,6 +58,7 @@ import static cz.muni.ics.oidc.server.connectors.PerunConnectorRpc.METHOD_GET_EN import static cz.muni.ics.oidc.server.connectors.PerunConnectorRpc.METHOD_GET_FACILITIES_BY_ATTRIBUTE; import static cz.muni.ics.oidc.server.connectors.PerunConnectorRpc.METHOD_GET_GROUPS_WHERE_USER_IS_ACTIVE; import static cz.muni.ics.oidc.server.connectors.PerunConnectorRpc.METHOD_GET_GROUP_BY_ID; +import static cz.muni.ics.oidc.server.connectors.PerunConnectorRpc.METHOD_GET_GROUP_BY_NAME; import static cz.muni.ics.oidc.server.connectors.PerunConnectorRpc.METHOD_GET_MEMBERS_BY_USER; import static cz.muni.ics.oidc.server.connectors.PerunConnectorRpc.METHOD_GET_MEMBER_BY_USER; import static cz.muni.ics.oidc.server.connectors.PerunConnectorRpc.METHOD_GET_MEMBER_GROUPS; @@ -80,6 +82,7 @@ import static cz.muni.ics.oidc.server.connectors.PerunConnectorRpc.PARAM_FACILIT import static cz.muni.ics.oidc.server.connectors.PerunConnectorRpc.PARAM_GROUP; import static cz.muni.ics.oidc.server.connectors.PerunConnectorRpc.PARAM_ID; import static cz.muni.ics.oidc.server.connectors.PerunConnectorRpc.PARAM_MEMBER; +import static cz.muni.ics.oidc.server.connectors.PerunConnectorRpc.PARAM_NAME; import static cz.muni.ics.oidc.server.connectors.PerunConnectorRpc.PARAM_RESOURCE; import static cz.muni.ics.oidc.server.connectors.PerunConnectorRpc.PARAM_SHORT_NAME; import static cz.muni.ics.oidc.server.connectors.PerunConnectorRpc.PARAM_USER; @@ -902,31 +905,15 @@ public class PerunAdapterRpc } @Override - public boolean isValidMemberInGroupsAndVos(Long userId, Set<Long> mandatoryVos, Set<Long> mandatoryGroups, - Set<Long> envVos, Set<Long> envGroups) { + public Set<String> getVosAndGroupsNamesWhereUserInvalid(Long userId, Set<Long> vos, Set<Long> groups) { if (!connectorRpc.isEnabled()) { - return false; + return new HashSet<>(); } - List<Member> members = getMembersByUser(userId); - Set<Long> foundVoIds = new HashSet<>(); - Set<Long> foundGroupIds = new HashSet<>(); - boolean skipGroups = mandatoryGroups.isEmpty() && envGroups.isEmpty(); - for (Member m : members) { - if (MemberStatus.VALID.equals(m.getStatus())) { - foundVoIds.add(m.getVoId()); - } - if (!skipGroups) { - foundGroupIds.addAll(getMemberGroups(m.getId()).stream().map(Model::getId).collect(Collectors.toList())); - } + if (vos == null) { + vos = new HashSet<>(); } - - return PerunAdapter.decideAccess(foundVoIds, foundGroupIds, mandatoryVos, mandatoryGroups, envVos, envGroups); - } - - @Override - public boolean isValidMemberInGroupsAndVos(Long userId, Set<Long> vos, Set<Long> groups) { - if (!connectorRpc.isEnabled()) { - return false; + if (groups == null) { + groups = new HashSet<>(); } List<Member> members = getMembersByUser(userId); Set<Long> foundVoIds = new HashSet<>(); @@ -942,7 +929,39 @@ public class PerunAdapterRpc } } - return PerunAdapter.decideAccess(foundVoIds, foundGroupIds, vos, groups); + Set<Long> voIdsToRegister = new HashSet<>(vos); + voIdsToRegister.removeAll(foundVoIds); + + Set<Long> groupIdsToRegister = new HashSet<>(groups); + groupIdsToRegister.removeAll(foundGroupIds); + + Set<String> unitNames = new HashSet<>(); + + final Map<Long, Vo> voCache = new HashMap<>(); + voIdsToRegister.forEach(voId -> { + Vo vo = getVoById(voId); + if (vo != null) { + voCache.put(vo.getId(), vo); + unitNames.add(vo.getShortName()); + } + }); + + + groupIdsToRegister.forEach(groupId -> { + Group group = getGroupById(groupId); + if (group != null) { + Vo vo = voCache.getOrDefault(group.getVoId(), null); + if (vo == null) { + vo = getVoById(group.getVoId()); + if (vo == null) { + return; + } + voCache.put(group.getVoId(), vo); + } + unitNames.add((vo.getShortName() + ":" + group.getName())); + } + }); + return unitNames; } @Override @@ -1019,6 +1038,50 @@ public class PerunAdapterRpc return voIds; } + @Override + public Map<Vo, Set<Group>> getRegistrationUnits(Set<String> invalidUnits) { + if (!connectorRpc.isEnabled()) { + return Collections.emptyMap(); + } + Map<String, Set<String>> voShortNamesToGroupNames = new HashMap<>(); + for (String invalidUnit : invalidUnits) { + String[] parts = invalidUnit.split(":", 2); + String voShortName = parts[0]; + voShortNamesToGroupNames.putIfAbsent(voShortName, new HashSet<>()); + if (parts.length > 1 && !PerunConstants.GROUP_NAME_MEMBERS.equals(parts[1])) { + voShortNamesToGroupNames.get(voShortName).add(parts[1]); + } + } + + Map<Vo, Set<Group>> res = new HashMap<>(); + for (Map.Entry<String, Set<String>> e : voShortNamesToGroupNames.entrySet()) { + Vo vo = getVoByShortName(e.getKey()); + if (vo != null && hasApplicationForm(vo.getId())) { + res.put(vo, new HashSet<>()); + for (String groupName : e.getValue()) { + Group group = getGroupByName(vo, groupName); + if (group != null && hasApplicationForm(vo.getId())) { + res.get(vo).add(group); + } + } + } + } + return res; + } + + private Group getGroupByName(Vo vo, String name) { + if (!connectorRpc.isEnabled()) { + return null; + } + + Map<String, Object> params = new LinkedHashMap<>(); + params.put(PARAM_VO, vo.getId()); + params.put(PARAM_NAME, name); + JsonNode jsonNode = connectorRpc.post(GROUPS_MANAGER, METHOD_GET_GROUP_BY_NAME, params); + + return RpcMapper.mapGroup(jsonNode); + } + private Member getMemberByUser(Long userId, Long voId) { if (!connectorRpc.isEnabled()) { return null; @@ -1122,6 +1185,18 @@ public class PerunAdapterRpc return RpcMapper.mapVo(res); } + private Group getGroupById(Long groupId) { + if (!connectorRpc.isEnabled()) { + return null; + } + + Map<String, Object> map = new LinkedHashMap<>(); + map.put(PARAM_ID, groupId); + + JsonNode res = connectorRpc.post(GROUPS_MANAGER, METHOD_GET_GROUP_BY_ID, map); + return RpcMapper.mapGroup(res); + } + private List<Group> getAssignedGroups(Long resourceId) { if (!connectorRpc.isEnabled()) { return new ArrayList<>(); @@ -1286,7 +1361,7 @@ public class PerunAdapterRpc Map<String, Object> map = new LinkedHashMap<>(); map.put(PARAM_GROUP, group.getId()); try { - if (group.getName().equalsIgnoreCase("members")) { + if (PerunConstants.GROUP_NAME_MEMBERS.equals(group.getName())) { log.debug("hasApplicationForm({}) continues to call regForm for VO {}", group, group.getVoId()); return hasApplicationForm(group.getVoId()); } else { diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/EntitlementExtendedClaimSource.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/EntitlementExtendedClaimSource.java index 4c8cb2279..33564198b 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/EntitlementExtendedClaimSource.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/EntitlementExtendedClaimSource.java @@ -1,6 +1,7 @@ package cz.muni.ics.oidc.server.claims.sources; import com.fasterxml.jackson.databind.JsonNode; +import cz.muni.ics.oidc.PerunConstants; import cz.muni.ics.oidc.models.Facility; import cz.muni.ics.oidc.models.Group; import cz.muni.ics.oidc.server.adapters.PerunAdapter; @@ -63,8 +64,8 @@ public class EntitlementExtendedClaimSource extends EntitlementSource { private void fillUuidEntitlements(Set<Group> userGroups, Set<String> entitlements) { for (Group group : userGroups) { String displayName = group.getUniqueGroupName(); - if (StringUtils.hasText(displayName) && MEMBERS.equals(group.getName())) { - displayName = displayName.replace(':' + MEMBERS, ""); + if (StringUtils.hasText(displayName) && PerunConstants.GROUP_NAME_MEMBERS.equals(group.getName())) { + displayName = displayName.replace(':' + PerunConstants.GROUP_NAME_MEMBERS, ""); } String entitlement = wrapGroupEntitlementToAARC(group.getUuid()); log.trace("{} - added UUID entitlement: '{}'", getClaimName(), entitlement); diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/EntitlementSource.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/EntitlementSource.java index 779f56e78..cbfc6c608 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/EntitlementSource.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/EntitlementSource.java @@ -2,6 +2,7 @@ package cz.muni.ics.oidc.server.claims.sources; import com.fasterxml.jackson.databind.JsonNode; import com.google.common.net.UrlEscapers; +import cz.muni.ics.oidc.PerunConstants; import cz.muni.ics.oidc.models.Facility; import cz.muni.ics.oidc.models.Group; import cz.muni.ics.oidc.models.PerunAttributeValue; @@ -137,8 +138,8 @@ public class EntitlementSource extends GroupNamesSource { } String[] parts = fullGname.split(":", 2); - if (parts.length == 2 && StringUtils.hasText(parts[1]) && MEMBERS.equals(parts[1])) { - parts[1] = parts[1].replace(MEMBERS, ""); + if (parts.length == 2 && StringUtils.hasText(parts[1]) && PerunConstants.GROUP_NAME_MEMBERS.equals(parts[1])) { + parts[1] = parts[1].replace(PerunConstants.GROUP_NAME_MEMBERS, ""); } String gname = parts[0]; diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/GroupNamesSource.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/GroupNamesSource.java index fa5db66a4..6a1dba456 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/GroupNamesSource.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/GroupNamesSource.java @@ -1,6 +1,7 @@ package cz.muni.ics.oidc.server.claims.sources; import com.fasterxml.jackson.databind.JsonNode; +import cz.muni.ics.oidc.PerunConstants; import cz.muni.ics.oidc.models.Facility; import cz.muni.ics.oidc.models.Group; import cz.muni.ics.oidc.server.claims.ClaimSource; @@ -25,8 +26,6 @@ import java.util.Set; @Slf4j public class GroupNamesSource extends ClaimSource { - protected static final String MEMBERS = "members"; - public GroupNamesSource(ClaimSourceInitContext ctx) { super(ctx); log.debug("{} - initialized", getClaimName()); @@ -57,8 +56,8 @@ public class GroupNamesSource extends ClaimSource { Map<Long, String> idToNameMap = new HashMap<>(); userGroups.forEach(g -> { String uniqueName = g.getUniqueGroupName(); - if (trimMembers && StringUtils.hasText(uniqueName) && MEMBERS.equals(g.getName())) { - uniqueName = uniqueName.replace(':' + MEMBERS, ""); + if (trimMembers && StringUtils.hasText(uniqueName) && PerunConstants.GROUP_NAME_MEMBERS.equals(g.getName())) { + uniqueName = uniqueName.replace(':' + PerunConstants.GROUP_NAME_MEMBERS, ""); g.setUniqueGroupName(uniqueName); } diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/connectors/PerunConnectorRpc.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/connectors/PerunConnectorRpc.java index e590c9acb..0f02c177b 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/connectors/PerunConnectorRpc.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/connectors/PerunConnectorRpc.java @@ -64,6 +64,7 @@ public class PerunConnectorRpc implements InitializingBean { public static final String PARAM_EXT_LOGIN = "extLogin"; public static final String PARAM_EXT_SOURCE_NAME = "extSourceName"; public static final String PARAM_SHORT_NAME = "shortName"; + public static final String PARAM_NAME = "name"; // METHODS @@ -94,6 +95,7 @@ public class PerunConnectorRpc implements InitializingBean { public static final String METHOD_GET_RICH_GROUPS_ASSIGNED_TO_RESOURCE_WITH_ATTRIBUTES_BY_NAMES = "getRichGroupsAssignedToResourceWithAttributesByNames"; public static final String METHOD_GET_USER_EXT_SOURCES = "getUserExtSources"; + public static final String METHOD_GET_GROUP_BY_NAME = "getGroupByName"; // VARIABLES diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/FiltersUtils.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/FiltersUtils.java index cf03b9c18..212c678ac 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/FiltersUtils.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/FiltersUtils.java @@ -1,16 +1,14 @@ package cz.muni.ics.oidc.server.filters; +import com.google.common.net.HttpHeaders; import cz.muni.ics.oauth2.model.ClientDetailsEntity; import cz.muni.ics.oauth2.model.DeviceCode; import cz.muni.ics.oauth2.service.ClientDetailsEntityService; -import cz.muni.ics.oidc.models.Facility; -import cz.muni.ics.oidc.models.PerunAttributeValue; import cz.muni.ics.oidc.models.PerunUser; import cz.muni.ics.oidc.saml.SamlProperties; import cz.muni.ics.oidc.server.adapters.PerunAdapter; -import cz.muni.ics.oidc.server.configurations.FacilityAttrsConfig; +import cz.muni.ics.oidc.server.configurations.PerunOidcConfig; import cz.muni.ics.oidc.web.controllers.ControllerUtils; -import cz.muni.ics.oidc.web.controllers.PerunUnapprovedRegistrationController; import cz.muni.ics.openid.connect.request.OAuth2RequestFactory; import lombok.extern.slf4j.Slf4j; import org.springframework.security.providers.ExpiringUsernameAuthenticationToken; @@ -19,8 +17,10 @@ import org.springframework.util.StringUtils; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; import java.util.AbstractMap; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; @@ -256,8 +256,8 @@ public class FiltersUtils { * @param req request wrapper object * @return Rebuilt URL. */ - public static String buildRequestURL(HttpServletRequest req) { - return buildRequestURL(req, null); + public static String reconstructRequestUrl(HttpServletRequest req) { + return reconstructRequestUrl(req, null); } /** @@ -266,7 +266,7 @@ public class FiltersUtils { * @param additionalParams parameters to be added * @return Rebuilt URL. */ - public static String buildRequestURL(HttpServletRequest req, Map<String, String> additionalParams) { + public static String reconstructRequestUrl(HttpServletRequest req, Map<String, String> additionalParams) { String returnURL = req.getRequestURL().toString(); if (req.getQueryString() != null) { @@ -287,75 +287,6 @@ public class FiltersUtils { return returnURL; } - /** - * Redirect user to the unapproved page. - * @param base Base URL - * @param response response object - * @param clientId identifier of the service - */ - public static void redirectUnapproved(String base, HttpServletResponse response, String clientId, String redirectMapping) - { - // cannot register, redirect to unapproved - Map<String, String> params = new HashMap<>(); - if (clientId != null) { - params.put("client_id", clientId); - } - - String redirectUrl = ControllerUtils.createRedirectUrl(base, redirectMapping, params); - response.reset(); - response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); - response.setHeader("Location", redirectUrl); - } - - /** - * Redirect user to the correct page when cannot access the service based on membership. - * @param base base URL - * @param response Response object - * @param facility Facility representing the client - * @param user User accessing the service - * @param clientIdentifier ClientID - * @param facilityAttrsConfig Config object for facility attributes - * @param facilityAttributes Actual facility attributes - * @param perunAdapter Adapter to call Perun - */ - public static void redirectUserCannotAccess(String base, - HttpServletResponse response, - Facility facility, - PerunUser user, - String clientIdentifier, - FacilityAttrsConfig facilityAttrsConfig, - PerunAdapter perunAdapter, - String redirectUrl) - { - Map<String, PerunAttributeValue> facilityAttributes = perunAdapter.getFacilityAttributeValues( - facility, facilityAttrsConfig.getMembershipAttrNames()); - if (facilityAttributes.get(facilityAttrsConfig.getAllowRegistrationAttr()).valueAsBoolean()) { - boolean canRegister = perunAdapter.getAdapterRpc().groupWhereCanRegisterExists(facility); - if (canRegister) { - PerunAttributeValue customRegUrlAttr = facilityAttributes.get(facilityAttrsConfig.getRegistrationURLAttr()); - if (customRegUrlAttr != null && customRegUrlAttr.valueAsString() != null) { - String customRegUrl = facilityAttributes.get(facilityAttrsConfig.getRegistrationURLAttr()).valueAsString(); - customRegUrl = validateUrl(customRegUrl); - if (customRegUrl != null) { - // redirect to custom registration URL - FiltersUtils.redirectToCustomRegUrl(response, customRegUrl, user); - return; - } - } - - if (facilityAttributes.get(facilityAttrsConfig.getDynamicRegistrationAttr()).valueAsBoolean()) { - // redirect to registration form - FiltersUtils.redirectToRegistrationForm(base, response, clientIdentifier, facility, user); - return; - } - } - } - - // cannot register, redirect to unapproved - log.debug("user cannot register to obtain access, redirecting user '{}' to unapproved page", user); - FiltersUtils.redirectUnapproved(base, response, clientIdentifier, redirectUrl); - } - public static String fillStringMandatoryProperty(String propertyName, String filterName, AuthProcFilterInitContext params) { @@ -376,28 +307,7 @@ public class FiltersUtils { return filled; } - private static void redirectToRegistrationForm(String base, HttpServletResponse response, - String clientIdentifier, Facility facility, PerunUser user) { - Map<String, String> params = new HashMap<>(); - params.put("client_id", clientIdentifier); - params.put("facility_id", facility.getId().toString()); - params.put("user_id", String.valueOf(user.getId())); - String redirectUrl = ControllerUtils.createRedirectUrl(base, - PerunUnapprovedRegistrationController.REGISTRATION_CONTINUE_MAPPING, params); - log.debug("redirecting user '{}' to the registration form URL: {}", user, redirectUrl); - response.reset(); - response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); - response.setHeader("Location", redirectUrl); - } - - private static void redirectToCustomRegUrl(HttpServletResponse response, String customRegUrl, PerunUser user) { - log.debug("redirecting user '{}' to the custom registration URL: {}", user, customRegUrl); - response.reset(); - response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); - response.setHeader("Location", customRegUrl); - } - - private static String validateUrl(String customRegUrl) { + public static String validateUrl(String customRegUrl) { return (customRegUrl == null || customRegUrl.isEmpty()) ? null : customRegUrl; } @@ -423,4 +333,5 @@ public class FiltersUtils { public static String getClientId(HttpServletRequest req) { return req.getParameter(AuthProcFilterConstants.PARAM_CLIENT_ID); } + } diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/IsEligibleFilter.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/IsEligibleFilter.java index 358586c95..e3dd1e739 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/IsEligibleFilter.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/IsEligibleFilter.java @@ -1,6 +1,7 @@ package cz.muni.ics.oidc.server.filters.impl; import cz.muni.ics.oidc.BeanUtil; +import cz.muni.ics.oidc.RedirectUtils; import cz.muni.ics.oidc.exceptions.ConfigurationException; import cz.muni.ics.oidc.saml.ExtendedOAuth2Exception; import cz.muni.ics.oidc.server.configurations.PerunOidcConfig; @@ -9,16 +10,12 @@ import cz.muni.ics.oidc.server.filters.AuthProcFilterCommonVars; import cz.muni.ics.oidc.server.filters.AuthProcFilterConstants; import cz.muni.ics.oidc.server.filters.AuthProcFilterInitContext; import cz.muni.ics.oidc.server.filters.FiltersUtils; -import cz.muni.ics.oidc.web.controllers.ControllerUtils; -import cz.muni.ics.oidc.web.controllers.PerunUnapprovedController; import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpHeaders; import org.springframework.security.saml.SAMLCredential; import org.springframework.util.StringUtils; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; @@ -26,6 +23,13 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import static cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController.SESS_ATTR_BUTTON_TRANSLATION; +import static cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController.SESS_ATTR_CLIENT; +import static cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController.SESS_ATTR_CONTACT_TRANSLATION; +import static cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController.SESS_ATTR_HEADER_TRANSLATION; +import static cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController.SESS_ATTR_TARGET; +import static cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController.SESS_ATTR_TEXT_TRANSLATION; +import static cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController.UNAUTHORIZED_IS_ELIGIBLE_MAPPING; import static cz.muni.ics.openid.connect.request.ConnectRequestParameters.PROMPT; import static cz.muni.ics.openid.connect.request.ConnectRequestParameters.PROMPT_NONE; import static cz.muni.ics.openid.connect.request.ConnectRequestParameters.REDIRECT_URI; @@ -50,16 +54,6 @@ public class IsEligibleFilter extends AuthProcFilter { public static final String APPLIED = "APPLIED_" + IsEligibleFilter.class.getSimpleName(); - public final static String DEFAULT_HEADER_TRANSLATION_KEY = "403_is_eligible_default_header_text"; - public final static String DEFAULT_TEXT_TRANSLATION_KEY = "403_is_eligible_default_text"; - public final static String DEFAULT_BUTTON_TRANSLATION_KEY = "403_is_eligible_default_button_text"; - public final static String DEFAULT_CONTACT_TRANSLATION_KEY = "403_is_eligible_default_contact_text"; - - public static final String HEADER_TRANSLATION = "header_translation"; - public static final String TEXT_TRANSLATION = "text_translation"; - public static final String BUTTON_TRANSLATION = "button_translation"; - public static final String CONTACT_TRANSLATION = "contact_translation"; - /* CONFIGURATION PROPERTIES */ private static final String SAML_ATTRIBUTE = "samlAttribute"; private static final String TRIGGER_SCOPE = "triggerScope"; @@ -78,6 +72,11 @@ public class IsEligibleFilter extends AuthProcFilter { /* END OF CONFIGURATION PROPERTIES */ + private static final String DEFAULT_HEADER_TRANSLATION_KEY = "403_is_eligible_default_header_text"; + private static final String DEFAULT_TEXT_TRANSLATION_KEY = "403_is_eligible_default_text"; + private static final String DEFAULT_BUTTON_TRANSLATION_KEY = "403_is_eligible_default_button_text"; + private static final String DEFAULT_CONTACT_TRANSLATION_KEY = "403_is_eligible_default_contact_text"; + private final String eligibleLastSeenSAMLAttributeName; private final String triggerScope; private final int validityPeriod; @@ -112,6 +111,7 @@ public class IsEligibleFilter extends AuthProcFilter { } } + this.oldValueHeaderTranslationKey = FiltersUtils.fillStringProperty( OLD_VALUE_HEADER_TRANSLATION_KEY, ctx, DEFAULT_HEADER_TRANSLATION_KEY); this.oldValueTextTranslationKey = FiltersUtils.fillStringProperty( @@ -185,17 +185,22 @@ public class IsEligibleFilter extends AuthProcFilter { } if (PROMPT_NONE.equals(req.getParameter(PROMPT))) { - throw new ExtendedOAuth2Exception("access_denied", "User does not meet the eligibility rules", req.getParameter(REDIRECT_URI), req.getParameter(STATE)); + throw new ExtendedOAuth2Exception( + "access_denied", "User does not meet the eligibility rules", + req.getParameter(REDIRECT_URI), req.getParameter(STATE) + ); } - HttpSession sess = req.getSession(true); - sess.setAttribute(HEADER_TRANSLATION, headerKey); - sess.setAttribute(TEXT_TRANSLATION, textKey); - sess.setAttribute(BUTTON_TRANSLATION, buttonKey); - sess.setAttribute(CONTACT_TRANSLATION, contactKey); + Map<String, Object> sessionAttributes = new HashMap<>(); + sessionAttributes.put(SESS_ATTR_HEADER_TRANSLATION, headerKey); + sessionAttributes.put(SESS_ATTR_TEXT_TRANSLATION, textKey); + sessionAttributes.put(SESS_ATTR_BUTTON_TRANSLATION, buttonKey); + sessionAttributes.put(SESS_ATTR_CONTACT_TRANSLATION, contactKey); + sessionAttributes.put(SESS_ATTR_CLIENT, params.getClient()); + log.debug("{} - attribute '{}' value is invalid, stop user at this point", filterName, eligibleLastSeenTimestamp); - this.redirect(req, res); + this.redirect(req, res, sessionAttributes); return false; } @@ -204,19 +209,11 @@ public class IsEligibleFilter extends AuthProcFilter { return false; } - private void redirect(HttpServletRequest req, HttpServletResponse res) { - Map<String, String> params = new HashMap<>(); - - String targetURL = FiltersUtils.buildRequestURL(req, + private void redirect(HttpServletRequest req, HttpServletResponse res, Map<String, Object> sessionAttributes) { + String targetURL = FiltersUtils.reconstructRequestUrl(req, Collections.singletonMap(AuthProcFilterConstants.PARAM_PROMPT, "login")); - params.put(AuthProcFilterConstants.PARAM_TARGET, targetURL); - - String redirectUrl = ControllerUtils.createRedirectUrl(config.getConfigBean().getIssuer(), - PerunUnapprovedController.UNAPPROVED_IS_ELIGIBLE_MAPPING, params); - log.debug("{} - redirecting user to unapproved: URL '{}'", filterName, redirectUrl); - res.reset(); - res.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); - res.setHeader(HttpHeaders.LOCATION, redirectUrl); + sessionAttributes.put(SESS_ATTR_TARGET, targetURL); + RedirectUtils.redirectInternal(req, res, config, UNAUTHORIZED_IS_ELIGIBLE_MAPPING, sessionAttributes); } } diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/PerunAuthorizationFilter.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/PerunAuthorizationFilter.java index 40929bae0..5de5efc0c 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/PerunAuthorizationFilter.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/PerunAuthorizationFilter.java @@ -1,5 +1,6 @@ package cz.muni.ics.oidc.server.filters.impl; +import cz.muni.ics.oauth2.model.ClientDetailsEntity; import cz.muni.ics.oidc.exceptions.ConfigurationException; import cz.muni.ics.oidc.models.Facility; import cz.muni.ics.oidc.models.PerunAttributeValue; @@ -11,14 +12,17 @@ import cz.muni.ics.oidc.server.configurations.PerunOidcConfig; import cz.muni.ics.oidc.server.filters.AuthProcFilter; import cz.muni.ics.oidc.server.filters.AuthProcFilterCommonVars; import cz.muni.ics.oidc.server.filters.AuthProcFilterInitContext; -import cz.muni.ics.oidc.server.filters.FiltersUtils; +import cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController; import lombok.extern.slf4j.Slf4j; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.util.HashMap; import java.util.Map; -import static cz.muni.ics.oidc.web.controllers.PerunUnapprovedController.UNAPPROVED_AUTHORIZATION; +import static cz.muni.ics.oidc.RedirectUtils.redirectExternal; +import static cz.muni.ics.oidc.RedirectUtils.redirectInternal; +import static cz.muni.ics.oidc.server.filters.FiltersUtils.validateUrl; import static cz.muni.ics.openid.connect.request.ConnectRequestParameters.PROMPT; import static cz.muni.ics.openid.connect.request.ConnectRequestParameters.PROMPT_NONE; import static cz.muni.ics.openid.connect.request.ConnectRequestParameters.REDIRECT_URI; @@ -73,8 +77,7 @@ public class PerunAuthorizationFilter extends AuthProcFilter { return true; } - return this.decideAccess(facility, user, req, res, params.getClientIdentifier(), - perunAdapter, facilityAttrsConfig, accessControlDisabledAttr); + return this.decideAccess(req, res, facility, user, params.getClient()); } @Override @@ -82,14 +85,11 @@ public class PerunAuthorizationFilter extends AuthProcFilter { return false; } - private boolean decideAccess(Facility facility, + private boolean decideAccess(HttpServletRequest req, + HttpServletResponse res, + Facility facility, PerunUser user, - HttpServletRequest req, - HttpServletResponse response, - String clientIdentifier, - PerunAdapter perunAdapter, - FacilityAttrsConfig facilityAttrsConfig, - String accessControlDisabledAttr) + ClientDetailsEntity client) { Map<String, PerunAttributeValue> facilityAttributes = perunAdapter.getFacilityAttributeValues( facility, facilityAttrsConfig.getMembershipAttrNames()); @@ -103,14 +103,107 @@ public class PerunAuthorizationFilter extends AuthProcFilter { log.info("{} - user allowed to access the service", getFilterName()); return true; } else { + log.info("{} - user is not allowed to access the service due to membership check", getFilterName()); if (PROMPT_NONE.equals(req.getParameter(PROMPT))) { throw new ExtendedOAuth2Exception("interaction_required", - "User needs to make further steps to be able to access the service.", req.getParameter(REDIRECT_URI), req.getParameter(STATE)); + "User needs to make further steps to be able to access the service.", + req.getParameter(REDIRECT_URI), + req.getParameter(STATE)); } - FiltersUtils.redirectUserCannotAccess(config.getConfigBean().getIssuer(), response, facility, user, - clientIdentifier, facilityAttrsConfig, perunAdapter, UNAPPROVED_AUTHORIZATION); + + redirectUserCannotAccess(req, res, facility, user, client); return false; } } + private void redirectUserCannotAccess(HttpServletRequest req, + HttpServletResponse res, + Facility facility, + PerunUser user, + ClientDetailsEntity client) + { + Map<String, PerunAttributeValue> facilityAttributes = perunAdapter.getFacilityAttributeValues( + facility, facilityAttrsConfig.getMembershipAttrNames() + ); + + if (allowsRegistration(facilityAttributes)) { + log.debug("{} - service '{}' allows registration", getFilterName(), client.getClientName()); + PerunAttributeValue customRegUrlAttr = facilityAttributes.get(facilityAttrsConfig.getRegistrationURLAttr()); + if (customRegUrlAttr != null && customRegUrlAttr.valueAsString() != null) { + String customRegUrl = facilityAttributes.get(facilityAttrsConfig.getRegistrationURLAttr()) + .valueAsString(); + log.debug("{} - service '{}' has a custom registration URL", getFilterName(), customRegUrl); + customRegUrl = validateUrl(customRegUrl); + if (customRegUrl != null) { + log.debug( + "{} - service '{}' registration URL '{}' passed validation. Redirecting user there.", + getFilterName(), client.getClientName(), customRegUrl + ); + redirectExternal(res, customRegUrl); + return; + } else { + log.debug( + "{} - service '{}' registration URL did not pass validation. Redirecting to unauthorized.", + getFilterName(), client.getClientName() + ); + } + } else { + boolean groupsForRegistrationExist = perunAdapter.getAdapterRpc().groupWhereCanRegisterExists(facility); + boolean dynamicRegistrationAllowed = + facilityAttributes.get(facilityAttrsConfig.getDynamicRegistrationAttr()).valueAsBoolean(); + if (groupsForRegistrationExist && dynamicRegistrationAllowed) { + log.debug( + "{} - service '{}' allows dynamic registration and some registration units exist. Redirecting user to the form to select VO (and GROUP)", + getFilterName(), client.getClientName() + ); + redirectChoosePerunEntities(req, res, user, client, facility); + return; + } else { + log.debug( + "{} - service '{}' has no registration option for user - units exist: {}, dynamic reg. allowed: {}", + getFilterName(), client.getClientName(), groupsForRegistrationExist, dynamicRegistrationAllowed + ); + } + } + } + + // cannot register, redirect to unauthorized + log.debug("User cannot register to obtain access (facility did not enable this), redirecting user '{}' to unauthorized page", user); + redirectUnauthorized(req, res, user, client); + } + + private boolean allowsRegistration(Map<String, PerunAttributeValue> facilityAttributes) { + return facilityAttributes.getOrDefault(facilityAttrsConfig.getAllowRegistrationAttr(), null) != null + && facilityAttributes.get(facilityAttrsConfig.getAllowRegistrationAttr()).valueAsBoolean(); + } + + private void redirectChoosePerunEntities(HttpServletRequest req, + HttpServletResponse res, + PerunUser user, + ClientDetailsEntity client, + Facility facility) + { + log.trace( + "{} - Redirecting user '{}' to the internal form to choose VO (and possibly GROUP)", + getFilterName(), user + ); + Map<String, Object> sessAttributes = new HashMap<>(); + sessAttributes.put(PerunUnauthorizedController.SESS_ATTR_USER, user); + sessAttributes.put(PerunUnauthorizedController.SESS_ATTR_CLIENT, client); + sessAttributes.put(PerunUnauthorizedController.SESS_ATTR_FACILITY, facility); + redirectInternal(req, res, config, PerunUnauthorizedController.UNAUTHORIZED_REGISTER_NOTIFY_ACTION_REQUIRED_MAPPING, sessAttributes); + } + + private void redirectUnauthorized(HttpServletRequest req, + HttpServletResponse res, + PerunUser user, + ClientDetailsEntity client) + { + log.debug("{} - Redirecting user '{}' to the internal page informing about unauthorized access", + getFilterName(), user); + Map<String, Object> sessAttributes = new HashMap<>(); + sessAttributes.put(PerunUnauthorizedController.SESS_ATTR_CLIENT, client); + redirectInternal(req, res, config, PerunUnauthorizedController.UNAUTHORIZED_AUTHORIZATION_MAPPING, sessAttributes); + } + } diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/PerunEnsureVoMember.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/PerunEnsureVoMember.java index 12cb21e60..09c28bda5 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/PerunEnsureVoMember.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/PerunEnsureVoMember.java @@ -1,6 +1,8 @@ package cz.muni.ics.oidc.server.filters.impl; +import cz.muni.ics.oauth2.model.ClientDetailsEntity; import cz.muni.ics.oidc.PerunConstants; +import cz.muni.ics.oidc.RedirectUtils; import cz.muni.ics.oidc.exceptions.ConfigurationException; import cz.muni.ics.oidc.models.Facility; import cz.muni.ics.oidc.models.PerunAttributeValue; @@ -12,10 +14,8 @@ import cz.muni.ics.oidc.server.filters.AuthProcFilterCommonVars; import cz.muni.ics.oidc.server.filters.AuthProcFilterInitContext; import cz.muni.ics.oidc.server.filters.FiltersUtils; import cz.muni.ics.oidc.web.controllers.ControllerUtils; -import cz.muni.ics.oidc.web.controllers.PerunUnapprovedController; -import cz.muni.ics.oidc.web.controllers.RegistrationController; +import cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController; import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpHeaders; import org.springframework.util.StringUtils; import javax.servlet.http.HttpServletRequest; @@ -25,6 +25,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import static cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController.SESS_ATTR_CLIENT; +import static cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController.SESS_ATTR_TARGET; +import static cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController.UNAUTHORIZED_ENSURE_VO_MAPPING; import static cz.muni.ics.openid.connect.request.ConnectRequestParameters.PROMPT; import static cz.muni.ics.openid.connect.request.ConnectRequestParameters.PROMPT_NONE; import static cz.muni.ics.openid.connect.request.ConnectRequestParameters.REDIRECT_URI; @@ -104,9 +107,12 @@ public class PerunEnsureVoMember extends AuthProcFilter { return true; } else { if (PROMPT_NONE.equals(req.getParameter(PROMPT))) { - throw new ExtendedOAuth2Exception("interaction_required", "User needs to register to VO", req.getParameter(REDIRECT_URI), req.getParameter(STATE)); + throw new ExtendedOAuth2Exception( + "interaction_required", "User needs to register to VO", + req.getParameter(REDIRECT_URI), req.getParameter(STATE) + ); } - redirect(res, getLoginUrl(facility.getId()), voShortName); + redirect(req, res, getLoginUrl(facility.getId()), voShortName, params.getClient()); return false; } } @@ -116,15 +122,31 @@ public class PerunEnsureVoMember extends AuthProcFilter { return false; } - private void redirect(HttpServletResponse response, PerunAttributeValue loginUrlAttr, String voShortName) { + @Override + public String toString() { + return "PerunEnsureVoMember{" + + "voDefsAttr='" + voDefsAttr + '\'' + + ", loginUrlAttr='" + loginUrlAttr + '\'' + + '}'; + } + + private void redirect(HttpServletRequest req, + HttpServletResponse res, + PerunAttributeValue loginUrlAttr, + String voShortName, + ClientDetailsEntity client) + { String loginUrl = null; if (loginUrlAttr != null && StringUtils.hasText(loginUrlAttr.valueAsString())) { loginUrl = loginUrlAttr.valueAsString(); } + if (StringUtils.hasText(voShortName) && perunAdapter.getAdapterRpc().hasApplicationForm(voShortName)) { - redirectDirectly(response, loginUrl, voShortName); + log.debug("{} - redirecting user to registration page for VO '{}'", getFilterName(), voShortName); + redirectRegistration(req, res, loginUrl, voShortName, client); } else { - redirectUnapproved(response); + log.debug("{} - redirecting user to unauthorized", getFilterName()); + redirectUnauthorized(req, res, client); } } @@ -136,23 +158,18 @@ public class PerunEnsureVoMember extends AuthProcFilter { } private PerunAttributeValue getVoDefsAttrValue(PerunAttributeValue attrValue) { - if (attrValue == null) { - return null; - } else if (attrValue.valueAsJson().isArray() && attrValue.valueAsJson().size() < 1) { + if (attrValue == null || (attrValue.valueAsJson().isArray() && attrValue.valueAsJson().size() < 1)) { return null; } return attrValue; } - @Override - public String toString() { - return "PerunEnsureVoMember{" + - "voDefsAttr='" + voDefsAttr + '\'' + - ", loginUrlAttr='" + loginUrlAttr + '\'' + - '}'; - } - - private void redirectDirectly(HttpServletResponse res, String loginUrl, String voShortName) { + private void redirectRegistration(HttpServletRequest req, + HttpServletResponse res, + String loginUrl, + String voShortName, + ClientDetailsEntity client) + { String registrarUrl = perunOidcConfig.getRegistrarUrl(); Map<String, String> params = new HashMap<>(); params.put(PerunConstants.REGISTRAR_PARAM_VO, voShortName); @@ -162,26 +179,24 @@ public class PerunEnsureVoMember extends AuthProcFilter { params.put(PerunConstants.REGISTRAR_TARGET_EXTENDED, loginUrl); } String target = ControllerUtils.createUrl(registrarUrl, params); + RedirectUtils.redirectInternal( + req, + res, + perunOidcConfig, + PerunUnauthorizedController.UNAUTHORIZED_REGISTER_NOTIFY_ACTION_REQUIRED_MAPPING, + Map.of(SESS_ATTR_TARGET, target, SESS_ATTR_CLIENT, client) + ); - String url = ControllerUtils.constructRequestUrl(perunOidcConfig, RegistrationController.CONTINUE_DIRECT_MAPPING); - params.clear(); - params.put(RegistrationController.PARAM_TARGET, target); - - String redirectUrl = ControllerUtils.createUrl(url, params); - log.debug("{} - redirecting user to '{}'", getFilterName(), redirectUrl); - res.reset(); - res.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); - res.setHeader(HttpHeaders.LOCATION, redirectUrl); } - private void redirectUnapproved(HttpServletResponse res) { - String redirectUrl = ControllerUtils.constructRequestUrl(perunOidcConfig, - PerunUnapprovedController.UNAPPROVED_ENSURE_VO_MAPPING); - - log.debug("{} - redirecting user to '{}'", getFilterName(), redirectUrl); - res.reset(); - res.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); - res.setHeader(HttpHeaders.LOCATION, redirectUrl); + private void redirectUnauthorized(HttpServletRequest req, HttpServletResponse res, ClientDetailsEntity client) { + RedirectUtils.redirectInternal( + req, + res, + perunOidcConfig, + UNAUTHORIZED_ENSURE_VO_MAPPING, + Map.of(SESS_ATTR_CLIENT, client) + ); } } diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/PerunIsTestSpFilter.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/PerunIsTestSpFilter.java index 96e8bfc71..b91d6e3ba 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/PerunIsTestSpFilter.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/PerunIsTestSpFilter.java @@ -1,5 +1,6 @@ package cz.muni.ics.oidc.server.filters.impl; +import cz.muni.ics.oidc.RedirectUtils; import cz.muni.ics.oidc.exceptions.ConfigurationException; import cz.muni.ics.oidc.models.Facility; import cz.muni.ics.oidc.models.PerunAttributeValue; @@ -11,18 +12,18 @@ import cz.muni.ics.oidc.server.filters.AuthProcFilterCommonVars; import cz.muni.ics.oidc.server.filters.AuthProcFilterInitContext; import cz.muni.ics.oidc.server.filters.FiltersUtils; import cz.muni.ics.oidc.web.controllers.ControllerUtils; -import cz.muni.ics.oidc.web.controllers.IsTestSpController; +import cz.muni.ics.oidc.web.controllers.TestSpWarningController; import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpHeaders; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; -import java.util.HashMap; import java.util.Map; import static cz.muni.ics.oidc.server.filters.AuthProcFilterConstants.PARAM_TARGET; -import static cz.muni.ics.oidc.web.controllers.IsTestSpController.IS_TEST_SP_APPROVED_SESS; +import static cz.muni.ics.oidc.web.controllers.TestSpWarningController.SESS_ATTR_IS_TEST_SP_APPROVED; +import static cz.muni.ics.oidc.web.controllers.TestSpWarningController.MAPPING; import static cz.muni.ics.openid.connect.request.ConnectRequestParameters.PROMPT; import static cz.muni.ics.openid.connect.request.ConnectRequestParameters.PROMPT_NONE; import static cz.muni.ics.openid.connect.request.ConnectRequestParameters.REDIRECT_URI; @@ -77,7 +78,7 @@ public class PerunIsTestSpFilter extends AuthProcFilter { throw new ExtendedOAuth2Exception("interaction_required", "User needs to acknowledge accessing a test service", req.getParameter(REDIRECT_URI), req.getParameter(STATE)); } - this.redirect(req, res); + redirect(req, res); return false; } log.debug("{} - service is not testing, let user access it", getFilterName()); @@ -94,24 +95,18 @@ public class PerunIsTestSpFilter extends AuthProcFilter { return false; } boolean approved = false; - if (req.getSession().getAttribute(IS_TEST_SP_APPROVED_SESS) != null) { - approved = (Boolean) req.getSession().getAttribute(IS_TEST_SP_APPROVED_SESS); - req.getSession().removeAttribute(IS_TEST_SP_APPROVED_SESS); + if (req.getSession().getAttribute(SESS_ATTR_IS_TEST_SP_APPROVED) != null) { + approved = (Boolean) req.getSession().getAttribute(SESS_ATTR_IS_TEST_SP_APPROVED); + req.getSession().removeAttribute(SESS_ATTR_IS_TEST_SP_APPROVED); } return approved; } private void redirect(HttpServletRequest req, HttpServletResponse res) { - String targetURL = FiltersUtils.buildRequestURL(req); + String target = FiltersUtils.reconstructRequestUrl(req); - Map<String, String> params = new HashMap<>(); - params.put(PARAM_TARGET, targetURL); - String redirectUrl = ControllerUtils.createRedirectUrl(config.getConfigBean().getIssuer(), - IsTestSpController.MAPPING, params); - log.debug("{} - redirecting user to testSP warning page: {}", getFilterName(), redirectUrl); - res.reset(); - res.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); - res.setHeader(HttpHeaders.LOCATION, redirectUrl); + log.debug("{} - redirecting user to testSP warning page: {}", getFilterName(), target); + RedirectUtils.redirectInternal(req, res, config, MAPPING, Map.of(TestSpWarningController.SESS_ATTR_TARGET, target)); } } diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/PerunLogIdentityFilter.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/PerunLogIdentityFilter.java index 7fe7bd203..01125beb1 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/PerunLogIdentityFilter.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/PerunLogIdentityFilter.java @@ -23,6 +23,7 @@ import javax.servlet.http.HttpServletResponse; @Slf4j public class PerunLogIdentityFilter extends AuthProcFilter { + public static final String EMPTY = "_empty"; private final String userIdentifierAttr; public PerunLogIdentityFilter(AuthProcFilterInitContext params) throws ConfigurationException { @@ -37,10 +38,10 @@ public class PerunLogIdentityFilter extends AuthProcFilter { SAMLCredential samlCredential = FiltersUtils.getSamlCredential(req); Long id = -1L; - String name = "_empty"; - String identifier = "_empty"; - String clientName = "_empty"; - String clientId = "_empty"; + String name = EMPTY; + String identifier = EMPTY; + String clientName = EMPTY; + String clientId = EMPTY; if (user != null) { name = user.getFirstName() + ' ' + user.getLastName(); id = user.getId(); diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/ProxyStatisticsFilter.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/ProxyStatisticsFilter.java index 82db0e3d6..15034f6f9 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/ProxyStatisticsFilter.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/ProxyStatisticsFilter.java @@ -127,7 +127,7 @@ public class ProxyStatisticsFilter extends AuthProcFilter { log.warn("{} - skip execution: no authenticating idp identifier provided", getFilterName()); return true; } else if (!StringUtils.hasText(samlCredential.getAttributeAsString(idpNameAttributeName))) { - log.warn("{} - skip execution: no authenticating idp identifier provided", getFilterName()); + log.warn("{} - skip execution: no authenticating idp name provided", getFilterName()); return true; } diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/ValidUserFilter.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/ValidUserFilter.java index fb9d418b1..9c11d8164 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/ValidUserFilter.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/filters/impl/ValidUserFilter.java @@ -1,9 +1,13 @@ package cz.muni.ics.oidc.server.filters.impl; +import cz.muni.ics.oauth2.model.ClientDetailsEntity; +import cz.muni.ics.oidc.RedirectUtils; import cz.muni.ics.oidc.exceptions.ConfigurationException; import cz.muni.ics.oidc.models.Facility; +import cz.muni.ics.oidc.models.Group; import cz.muni.ics.oidc.models.PerunAttributeValue; import cz.muni.ics.oidc.models.PerunUser; +import cz.muni.ics.oidc.models.Vo; import cz.muni.ics.oidc.saml.ExtendedOAuth2Exception; import cz.muni.ics.oidc.server.adapters.PerunAdapter; import cz.muni.ics.oidc.server.configurations.FacilityAttrsConfig; @@ -12,13 +16,15 @@ import cz.muni.ics.oidc.server.filters.AuthProcFilter; import cz.muni.ics.oidc.server.filters.AuthProcFilterCommonVars; import cz.muni.ics.oidc.server.filters.AuthProcFilterInitContext; import cz.muni.ics.oidc.server.filters.FiltersUtils; -import cz.muni.ics.oidc.web.controllers.PerunUnapprovedController; +import cz.muni.ics.oidc.web.controllers.PerunUnauthorizedController; import lombok.extern.slf4j.Slf4j; import org.springframework.util.StringUtils; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; import static cz.muni.ics.openid.connect.request.ConnectRequestParameters.PROMPT; @@ -60,7 +66,6 @@ public class ValidUserFilter extends AuthProcFilter { private static final String TEST_ENV_VOS = "testEnvVos"; private static final String PROD_ENV_GROUPS = "prodEnvGroups"; private static final String PROD_ENV_VOS = "prodEnvVos"; - private final Set<Long> allEnvGroups; private final Set<Long> allEnvVos; private final Set<Long> testEnvGroups; @@ -111,42 +116,27 @@ public class ValidUserFilter extends AuthProcFilter { return true; } - if (!checkMemberValidInGroupsAndVos(user, allEnvVos, allEnvGroups)) { - if (PROMPT_NONE.equals(req.getParameter(PROMPT))) { - throw new ExtendedOAuth2Exception("interaction_required", - "User needs to make further steps to be able to access the service.", req.getParameter(REDIRECT_URI), req.getParameter(STATE)); - } - redirectCannotAccess(res, facility, user, params.getClientIdentifier(), PerunUnapprovedController.UNAPPROVED_NOT_IN_MANDATORY_VOS_GROUPS); - return false; - } - - PerunAttributeValue isTestSpAttrValue = perunAdapter.getFacilityAttributeValue(facility.getId(), facilityAttrsConfig.getTestSpAttr()); + PerunAttributeValue isTestSpAttrValue = perunAdapter.getFacilityAttributeValue( + facility.getId(), facilityAttrsConfig.getTestSpAttr()); boolean testService = false; if (isTestSpAttrValue != null) { testService = isTestSpAttrValue.valueAsBoolean(); } - log.debug("{} - service {} in test env", getFilterName(), (testService ? "is" : "is not")); - - Set<Long> vos = new HashSet<>(); - Set<Long> groups = new HashSet<>(); - String unapprovedMapping; + Set<Long> vos = new HashSet<>(allEnvVos); + Set<Long> groups = new HashSet<>(allEnvGroups); if (testService) { vos.addAll(testEnvVos); groups.addAll(testEnvGroups); - unapprovedMapping = PerunUnapprovedController.UNAPPROVED_NOT_IN_TEST_VOS_GROUPS; } else { vos.addAll(prodEnvVos); groups.addAll(prodEnvGroups); - unapprovedMapping = PerunUnapprovedController.UNAPPROVED_NOT_IN_PROD_VOS_GROUPS; } - if (!checkMemberValidInGroupsAndVos(user, vos, groups)) { - log.info("{} - Redirecting to unapproved page with mapping '{}'", getFilterName(), unapprovedMapping); - if (PROMPT_NONE.equals(req.getParameter(PROMPT))) { - throw new ExtendedOAuth2Exception("interaction_required", - "User needs to make further steps to be able to access the service.", req.getParameter(REDIRECT_URI), req.getParameter(STATE)); - } - redirectCannotAccess(res, facility, user, params.getClientIdentifier(), unapprovedMapping); + + Set<String> invalidUnits = getVosAndGroupsNamesWhereUserInvalid(user, vos, groups); + if (!invalidUnits.isEmpty()) { + respondToPrompt(req); + redirectCannotAccess(req, res, invalidUnits, params.getClient()); return false; } @@ -154,16 +144,33 @@ public class ValidUserFilter extends AuthProcFilter { return true; } + private void redirectCannotAccess(HttpServletRequest req, + HttpServletResponse res, + Set<String> invalidUnits, + ClientDetailsEntity client) + { + Map<Vo, Set<Group>> registrationUnits = perunAdapter.getAdapterRpc().getRegistrationUnits(invalidUnits); + + Map<String, Object> sessParams = new HashMap<>(); + sessParams.put(PerunUnauthorizedController.SESS_ATTR_REGISTRATION_UNITS, registrationUnits); + sessParams.put(PerunUnauthorizedController.SESS_ATTR_CLIENT, client); + RedirectUtils.redirectInternal(req, res, config, PerunUnauthorizedController.UNAUTHORIZED_NOT_IN_ENV_VOS_GROUPS_MAPPING, sessParams); + } + @Override protected boolean oncePerSession() { return false; } - private void redirectCannotAccess(HttpServletResponse res, Facility facility, PerunUser user, - String clientId, String mapping) - { - FiltersUtils.redirectUserCannotAccess(config.getConfigBean().getIssuer(), res, facility, user, - clientId, facilityAttrsConfig, perunAdapter, mapping); + private void respondToPrompt(HttpServletRequest req) { + if (PROMPT_NONE.equals(req.getParameter(PROMPT))) { + throw new ExtendedOAuth2Exception( + "interaction_required", + "User needs to make further steps to be able to access the service.", + req.getParameter(REDIRECT_URI), + req.getParameter(STATE) + ); + } } private Set<Long> getIdsFromParam(AuthProcFilterInitContext params, String propKey) { @@ -180,14 +187,14 @@ public class ValidUserFilter extends AuthProcFilter { return result; } - private boolean checkMemberValidInGroupsAndVos(PerunUser user, Set<Long> vos, Set<Long> groups) { - if (!perunAdapter.isValidMemberInGroupsAndVos(user.getId(), vos, groups)) { + private Set<String> getVosAndGroupsNamesWhereUserInvalid(PerunUser user, Set<Long> vos, Set<Long> groups) { + Set<String> invalidUnits = perunAdapter.getVosAndGroupsNamesWhereUserInvalid(user.getId(), vos, groups); + if (!invalidUnits.isEmpty()) { log.info("{} - user is not member in required set of vos and groups", getFilterName()); - log.debug("{} - user: '{}', vos: '{}', groups: '{}'", - getFilterName(), user.getId(), vos, groups); - return false; + log.debug("{} - user: '{}', vos: '{}', groups: '{}', invalid units: '{}", + getFilterName(), user.getId(), vos, groups, invalidUnits); } - return true; + return invalidUnits; } } diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/AupController.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/AupController.java index 4367f0d35..07df0759a 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/AupController.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/AupController.java @@ -41,19 +41,22 @@ public class AupController { public static final String RETURN_URL = "returnUrl"; public static final String USER_ATTR = "userAttr"; - private static final SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd"); + private static final SimpleDateFormat FORMATTER = new SimpleDateFormat("yyyy-MM-dd"); - private final JsonNodeFactory jsonNodeFactory = JsonNodeFactory.instance; private final ObjectMapper mapper = new ObjectMapper(); - @Autowired - private PerunAdapter perunAdapter; + private final PerunAdapter perunAdapter; - @Autowired - private PerunOidcConfig perunOidcConfig; + private final PerunOidcConfig perunOidcConfig; + + private final WebHtmlClasses htmlClasses; @Autowired - private WebHtmlClasses htmlClasses; + public AupController(PerunAdapter perunAdapter, PerunOidcConfig perunOidcConfig, WebHtmlClasses htmlClasses) { + this.perunAdapter = perunAdapter; + this.perunOidcConfig = perunOidcConfig; + this.htmlClasses = htmlClasses; + } @GetMapping(value = "/" + URL) public String showAup(HttpServletRequest req, @@ -81,7 +84,7 @@ public class AupController { @SessionAttribute(name = USER_ATTR) String userAupsAttrName) throws IOException { JsonNode aupsToApproveJson = mapper.readTree(newAupsString); - ObjectNode aupsToApproveJsonObject = new ObjectNode(jsonNodeFactory); + ObjectNode aupsToApproveJsonObject = new ObjectNode(JsonNodeFactory.instance); Iterator<Map.Entry<String, JsonNode>> iterator = aupsToApproveJson.fields(); while (iterator.hasNext()) { @@ -89,7 +92,7 @@ public class AupController { ObjectNode aup = (ObjectNode) keyAupPair.getValue(); Date date = new Date(System.currentTimeMillis()); - aup.put(Aup.SIGNED_ON, formatter.format(date)); + aup.put(Aup.SIGNED_ON, FORMATTER.format(date)); if (aupsToApproveJsonObject.has(keyAupPair.getKey())) { aupsToApproveJsonObject.replace(keyAupPair.getKey(), aup); @@ -128,7 +131,7 @@ public class AupController { private ObjectNode updateUserAupsAttrValue(ObjectNode userAups, ObjectNode newAups) throws IOException { if (userAups == null) { - userAups = new ObjectNode(jsonNodeFactory); + userAups = JsonNodeFactory.instance.objectNode(); } Iterator<Map.Entry<String, JsonNode>> newAupsFields = newAups.fields(); @@ -146,7 +149,7 @@ public class AupController { } if (oldAupsArray == null) { - oldAupsArray = new ArrayNode(jsonNodeFactory); + oldAupsArray = JsonNodeFactory.instance.arrayNode(); } oldAupsArray.add(newApprovedAup); diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/ControllerUtils.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/ControllerUtils.java index 5e0433c01..229da1011 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/ControllerUtils.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/ControllerUtils.java @@ -46,14 +46,17 @@ public class ControllerUtils { private static final String LANG_KEY = "lang"; private static final String REQ_URL_KEY = "reqURL"; private static final String LANGS_MAP_KEY = "langsMap"; - public static final String LANG_PROPS_KEY = "langProps"; + + private ControllerUtils() { + // disallow instantiation + } /** * Set language properties for page. * @param model model object * @param req request object - * @param localization localization with texts + * @param config configuration bean */ public static void setLanguageForPage(Map<String, Object> model, HttpServletRequest req, PerunOidcConfig config) { String langFromParam = req.getParameter(LANG_KEY); @@ -145,6 +148,16 @@ public class ControllerUtils { model.put("contactMail", perunOidcConfig.getEmailContact()); } + public static void setPageOptions(Map<String, Object> model, + HttpServletRequest req, + WebHtmlClasses classes, + PerunOidcConfig perunOidcConfig, + String page) { + setLanguageForPage(model, req, perunOidcConfig); + setPageOptions(model, req, classes, perunOidcConfig); + model.put("page", page); + } + /** * Set scopes and claims for consent page. @@ -213,21 +226,20 @@ public class ControllerUtils { model.put(SCOPES, sortedScopes); } - private static String transformObject(JsonObject obj) { - StringJoiner sj = new StringJoiner(", "); - for (String s: obj.keySet()) { - sj.add(s + ": " + obj.get(s).getAsString()); - } - return sj.toString(); - } + public static Set<SystemScope> getSortedScopes(Set<String> requestedScopes, SystemScopeService scopeService) { + Set<SystemScope> scopes = scopeService.fromStrings(requestedScopes); + Set<SystemScope> sortedScopes = new LinkedHashSet<>(scopes.size()); + Set<SystemScope> systemScopes = scopeService.getAll(); - private static String transformArray(JsonArray arr) { - StringJoiner sj = new StringJoiner(", "); - for (int i = 0; i < arr.size(); i++) { - sj.add(arr.get(i).getAsString()); + for (SystemScope s : systemScopes) { + if (scopes.contains(s)) { + sortedScopes.add(s); + } } - return sj.toString(); + + sortedScopes.addAll(Sets.difference(scopes, systemScopes)); + return sortedScopes; } /** @@ -246,14 +258,10 @@ public class ControllerUtils { if (it.hasNext()) { while (it.hasNext()) { Map.Entry<String, String> param = it.next(); - try { - if (param.getKey() != null && param.getValue() != null) { - String encodedValue = URLEncoder.encode(param.getValue(), - StandardCharsets.UTF_8.toString()); - sb.append(param.getKey()).append('=').append(encodedValue); - } - } catch (UnsupportedEncodingException e) { - //TODO: handle + if (param.getKey() != null && param.getValue() != null) { + String encodedValue = URLEncoder.encode(param.getValue(), + StandardCharsets.UTF_8); + sb.append(param.getKey()).append('=').append(encodedValue); } if (it.hasNext()) { sb.append('&'); @@ -278,6 +286,25 @@ public class ControllerUtils { return url + newPath; } + + private static String transformObject(JsonObject obj) { + StringJoiner sj = new StringJoiner(", "); + for (String s: obj.keySet()) { + sj.add(s + ": " + obj.get(s).getAsString()); + } + return sj.toString(); + } + + + private static String transformArray(JsonArray arr) { + StringJoiner sj = new StringJoiner(", "); + for (int i = 0; i < arr.size(); i++) { + sj.add(arr.get(i).getAsString()); + } + return sj.toString(); + } + + private static String removeQueryParameter(String url, String parameterName) throws URISyntaxException { URIBuilder uriBuilder = new URIBuilder(url); @@ -311,20 +338,4 @@ public class ControllerUtils { } } - public static Set<SystemScope> getSortedScopes(Set<String> requestedScopes, SystemScopeService scopeService) { - Set<SystemScope> scopes = scopeService.fromStrings(requestedScopes); - - Set<SystemScope> sortedScopes = new LinkedHashSet<>(scopes.size()); - Set<SystemScope> systemScopes = scopeService.getAll(); - - for (SystemScope s : systemScopes) { - if (scopes.contains(s)) { - sortedScopes.add(s); - } - } - - sortedScopes.addAll(Sets.difference(scopes, systemScopes)); - return sortedScopes; - } - } diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/IsTestSpController.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/IsTestSpController.java deleted file mode 100644 index 5c1dc2bb6..000000000 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/IsTestSpController.java +++ /dev/null @@ -1,65 +0,0 @@ -package cz.muni.ics.oidc.web.controllers; - -import cz.muni.ics.oidc.server.configurations.PerunOidcConfig; -import cz.muni.ics.oidc.web.WebHtmlClasses; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; -import java.util.Map; - -import static cz.muni.ics.oidc.server.filters.AuthProcFilterConstants.PARAM_ACCEPTED; -import static cz.muni.ics.oidc.server.filters.AuthProcFilterConstants.PARAM_TARGET; - -/** - * Controller for IS TEST SP pages. - * - * @author Pavol Pluta <pavol.pluta1@gmail.com> - */ -@Controller -@Slf4j -public class IsTestSpController { - - public static final String MAPPING = "/testRpWarning"; - public static final String IS_TEST_SP_APPROVED_SESS = "isTestSpApprovedSession"; - private static final String TARGET = "target"; - private static final String ACTION = "action"; - - private final WebHtmlClasses htmlClasses; - private final PerunOidcConfig perunOidcConfig; - - @Autowired - public IsTestSpController(WebHtmlClasses htmlClasses, PerunOidcConfig perunOidcConfig) { - this.htmlClasses = htmlClasses; - this.perunOidcConfig = perunOidcConfig; - } - - @GetMapping(value = MAPPING, params = PARAM_TARGET) - public String isTestSpWarning(HttpServletRequest req, - Map<String, Object> model, - @RequestParam(PARAM_TARGET) String returnUrl) - { - log.debug("Display warning page for isTestSp"); - model.put(TARGET, returnUrl); - model.put(ACTION, req.getRequestURL().toString()); - ControllerUtils.setPageOptions(model, req, htmlClasses, perunOidcConfig); - return "isTestSpWarning"; - } - - @GetMapping(value = MAPPING, params = {PARAM_TARGET, PARAM_ACCEPTED}) - public String warningApproved(HttpServletRequest request, - @RequestParam(PARAM_TARGET) String target) - { - log.debug("Warning approved, set session attribute and redirect to {}", target); - HttpSession sess = request.getSession(); - if (sess != null) { - sess.setAttribute(IS_TEST_SP_APPROVED_SESS, true); - } - return "redirect:" + target; - } - -} diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/LoginController.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/LoginController.java index 536214c27..1e7174e57 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/LoginController.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/LoginController.java @@ -21,8 +21,6 @@ public class LoginController { public static final String MAPPING_SUCCESS = "/login_success"; public static final String MAPPING_FAILURE = "/login_failure"; - - public static final String KEY_ERROR_MSG = "error_msg"; public static final String ATTR_EXCEPTION = "exception_in_auth"; private final WebHtmlClasses htmlClasses; @@ -60,7 +58,6 @@ public class LoginController { model.put(JsonErrorView.ERROR, "unmet_authentication_requirements"); model.put(JsonErrorView.ERROR_MESSAGE, "Cannot log in. MFA has been requested and not performed"); return JsonErrorView.VIEWNAME; - //model.put(KEY_ERROR_MSG, "login_failure.no_authn_context.msg"); } } } diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/PerunUnapprovedController.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/PerunUnapprovedController.java deleted file mode 100644 index b9817c968..000000000 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/PerunUnapprovedController.java +++ /dev/null @@ -1,255 +0,0 @@ -package cz.muni.ics.oidc.web.controllers; - -import cz.muni.ics.oauth2.model.ClientDetailsEntity; -import cz.muni.ics.oauth2.service.ClientDetailsEntityService; -import cz.muni.ics.oidc.server.configurations.PerunOidcConfig; -import cz.muni.ics.oidc.web.WebHtmlClasses; -import cz.muni.ics.openid.connect.view.HttpCodeView; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; -import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; -import org.springframework.stereotype.Controller; -import org.springframework.util.StringUtils; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.SessionAttribute; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import java.util.Map; - -import static cz.muni.ics.oidc.server.filters.AuthProcFilterConstants.PARAM_CLIENT_ID; -import static cz.muni.ics.oidc.server.filters.AuthProcFilterConstants.PARAM_HEADER; -import static cz.muni.ics.oidc.server.filters.AuthProcFilterConstants.PARAM_MESSAGE; -import static cz.muni.ics.oidc.server.filters.AuthProcFilterConstants.PARAM_TARGET; -import static cz.muni.ics.oidc.server.filters.impl.IsEligibleFilter.BUTTON_TRANSLATION; -import static cz.muni.ics.oidc.server.filters.impl.IsEligibleFilter.CONTACT_TRANSLATION; -import static cz.muni.ics.oidc.server.filters.impl.IsEligibleFilter.DEFAULT_BUTTON_TRANSLATION_KEY; -import static cz.muni.ics.oidc.server.filters.impl.IsEligibleFilter.DEFAULT_CONTACT_TRANSLATION_KEY; -import static cz.muni.ics.oidc.server.filters.impl.IsEligibleFilter.DEFAULT_HEADER_TRANSLATION_KEY; -import static cz.muni.ics.oidc.server.filters.impl.IsEligibleFilter.DEFAULT_TEXT_TRANSLATION_KEY; -import static cz.muni.ics.oidc.server.filters.impl.IsEligibleFilter.HEADER_TRANSLATION; -import static cz.muni.ics.oidc.server.filters.impl.IsEligibleFilter.TEXT_TRANSLATION; - -/** - * Ctonroller for the unapproved page. - * - * @author Dominik Frantisek Bucik <bucik@ics.muni.cz> - */ -@Controller -@Slf4j -public class PerunUnapprovedController { - - public static final String UNAPPROVED_MAPPING = "/unapproved"; - public static final String UNAPPROVED_SPECIFIC_MAPPING = "/unapproved_spec"; - public static final String UNAPPROVED_IS_ELIGIBLE_MAPPING = "/unapprovedNotEligible"; - public static final String UNAPPROVED_ENSURE_VO_MAPPING = "/unapprovedEnsureVo"; - public static final String UNAPPROVED_AUTHORIZATION = "/unapprovedAuthorization"; - public static final String UNAPPROVED_NOT_IN_TEST_VOS_GROUPS = "/unapprovedNotInTestVosGroups"; - public static final String UNAPPROVED_NOT_IN_PROD_VOS_GROUPS = "/unapprovedNotInProdVosGroups"; - public static final String UNAPPROVED_NOT_IN_MANDATORY_VOS_GROUPS = "/unapprovedNotInMandatoryVosGroups"; - public static final String UNAPPROVED_NOT_LOGGED_IN = "/unapprovedNotLoggedIn"; - - private static final String OUT_HEADER = "outHeader"; - private static final String OUT_MESSAGE = "outMessage"; - private static final String OUT_BUTTON = "outButton"; - private static final String OUT_CONTACT_P = "outContactP"; - - private static final String ENSURE_VO_HDR = "403_ensure_vo_hdr"; - private static final String ENSURE_VO_MSG = "403_ensure_vo_msg"; - - private static final String AUTHORIZATION_HDR = "403_authorization_hdr"; - private static final String AUTHORIZATION_MSG = "403_authorization_msg"; - - private static final String NOT_IN_TEST_VOS_GROUPS_HDR = "403_not_in_test_vos_groups_hdr"; - private static final String NOT_IN_TEST_VOS_GROUPS_MSG = "403_not_in_test_vos_groups_msg"; - - private static final String NOT_IN_PROD_VOS_GROUPS_HDR = "403_not_in_prod_vos_groups_hdr"; - private static final String NOT_IN_PROD_VOS_GROUPS_MSG = "403_not_in_prod_vos_groups_msg"; - - private static final String NOT_IN_MANDATORY_VOS_GROUPS_HDR = "403_not_in_mandatory_vos_groups_hdr"; - private static final String NOT_IN_MANDATORY_VOS_GROUPS_MSG = "403_not_in_mandatory_vos_groups_msg"; - - private static final String NOT_LOGGED_IN_HDR = "403_not_logged_in_hdr"; - private static final String NOT_LOGGED_IN_MSG = "403_not_logged_in_msg"; - - private static final String CONTACT_LANG_PROP_KEY = "contact_p"; - private static final String CONTACT_MAIL = "contactMail"; - private static final String HAS_TARGET = "hasTarget"; - private static final String REASON = "reason"; - - public static final String TARGET = "target"; - - @Autowired - private ClientDetailsEntityService clientService; - - @Autowired - private PerunOidcConfig perunOidcConfig; - - @Autowired - private WebHtmlClasses htmlClasses; - - @Autowired - private SecurityContextLogoutHandler logoutHandler; - - @GetMapping(value = UNAPPROVED_MAPPING) - public String showUnapproved(HttpServletRequest req, - Map<String, Object> model, - @RequestParam(PARAM_CLIENT_ID) String clientId) - { - ClientDetailsEntity client; - - try { - client = clientService.loadClientByClientId(clientId); - } catch (OAuth2Exception e) { - log.error("showUnapproved: OAuth2Exception was thrown when attempting to load client", e); - model.put(HttpCodeView.CODE, HttpStatus.NOT_FOUND); - return HttpCodeView.VIEWNAME; - } catch (IllegalArgumentException e) { - log.error("showUnapproved: IllegalArgumentException was thrown when attempting to load client", e); - model.put(HttpCodeView.CODE, HttpStatus.BAD_REQUEST); - return HttpCodeView.VIEWNAME; - } - - if (client == null) { - log.error("showUnapproved: could not find client " + clientId); - model.put(HttpCodeView.CODE, HttpStatus.NOT_FOUND); - return HttpCodeView.VIEWNAME; - } - - ControllerUtils.setPageOptions(model, req, htmlClasses, perunOidcConfig); - model.put("client", client); - return "unapproved"; - } - - @GetMapping(value = UNAPPROVED_SPECIFIC_MAPPING) - public String showUnapprovedSpec(HttpServletRequest req, Map<String, Object> model, - @RequestParam(value = PARAM_HEADER, required = false) String header, - @RequestParam(value = PARAM_MESSAGE, required = false) String message) - { - ControllerUtils.setPageOptions(model, req, htmlClasses, perunOidcConfig); - - model.put(OUT_HEADER, header); - model.put(OUT_MESSAGE, message); - model.put(OUT_CONTACT_P, CONTACT_LANG_PROP_KEY); - model.put(CONTACT_MAIL, perunOidcConfig.getEmailContact()); - return "unapproved_spec"; - } - - @GetMapping(value = UNAPPROVED_IS_ELIGIBLE_MAPPING) - public String showUnapprovedIsEligible(HttpServletRequest req, - Map<String, Object> model, - @RequestParam(value = PARAM_TARGET, required = false) String target) - { - ControllerUtils.setPageOptions(model, req, htmlClasses, perunOidcConfig); - - HttpSession sess = req.getSession(); - String header = loadSessionTranslationKey(sess, HEADER_TRANSLATION, DEFAULT_HEADER_TRANSLATION_KEY); - String message = loadSessionTranslationKey(sess, TEXT_TRANSLATION, DEFAULT_TEXT_TRANSLATION_KEY); - String button = loadSessionTranslationKey(sess, BUTTON_TRANSLATION, DEFAULT_BUTTON_TRANSLATION_KEY); - String contactP = loadSessionTranslationKey(sess, CONTACT_TRANSLATION, DEFAULT_CONTACT_TRANSLATION_KEY); - - model.put(OUT_HEADER, header); - model.put(OUT_MESSAGE, message); - model.put(OUT_BUTTON, button); - model.put(OUT_CONTACT_P, contactP); - model.put(CONTACT_MAIL, perunOidcConfig.getEmailContact()); - model.put(HAS_TARGET, StringUtils.hasText(target)); - req.getSession(true).setAttribute(TARGET, target); - return "unapproved_is_eligible"; - } - - @PostMapping(value = UNAPPROVED_IS_ELIGIBLE_MAPPING) - public String showUnapprovedIsEligibleHandle(HttpServletRequest req, - HttpServletResponse res, - Map<String, Object> model, - @SessionAttribute(PARAM_TARGET) String target) - { - if (!StringUtils.hasText(target)) { - return showUnapprovedIsEligible(req, model, null); - } else { - logoutHandler.logout(req, res, null); - return "redirect:" + target; - } - } - - @GetMapping(value = UNAPPROVED_ENSURE_VO_MAPPING) - public String showUnapprovedEnsureVo(HttpServletRequest req, Map<String, Object> model) { - ControllerUtils.setPageOptions(model, req, htmlClasses, perunOidcConfig); - - model.put(OUT_HEADER, ENSURE_VO_HDR); - model.put(OUT_MESSAGE, ENSURE_VO_MSG); - model.put(OUT_CONTACT_P, CONTACT_LANG_PROP_KEY); - model.put(CONTACT_MAIL, perunOidcConfig.getEmailContact()); - - return "unapproved_spec"; - } - - @GetMapping(value = UNAPPROVED_AUTHORIZATION) - public String showUnapprovedAuthorization(HttpServletRequest req, Map<String, Object> model) { - ControllerUtils.setPageOptions(model, req, htmlClasses, perunOidcConfig); - - model.put(OUT_HEADER, AUTHORIZATION_HDR); - model.put(OUT_MESSAGE, AUTHORIZATION_MSG); - model.put(OUT_CONTACT_P, CONTACT_LANG_PROP_KEY); - model.put(CONTACT_MAIL, perunOidcConfig.getEmailContact()); - return "unapproved_spec"; - } - - @GetMapping(value = UNAPPROVED_NOT_IN_TEST_VOS_GROUPS) - public String showUnapprovedNotInTestVosGroups(HttpServletRequest req, Map<String, Object> model) { - ControllerUtils.setPageOptions(model, req, htmlClasses, perunOidcConfig); - - model.put(OUT_HEADER, NOT_IN_TEST_VOS_GROUPS_HDR); - model.put(OUT_MESSAGE, NOT_IN_TEST_VOS_GROUPS_MSG); - model.put(OUT_CONTACT_P, CONTACT_LANG_PROP_KEY); - model.put(CONTACT_MAIL, perunOidcConfig.getEmailContact()); - return "unapproved_spec"; - } - - @GetMapping(value = UNAPPROVED_NOT_IN_PROD_VOS_GROUPS) - public String showUnapprovedNotInProdVosGroups(HttpServletRequest req, Map<String, Object> model) { - ControllerUtils.setPageOptions(model, req, htmlClasses, perunOidcConfig); - - model.put(OUT_HEADER, NOT_IN_PROD_VOS_GROUPS_HDR); - model.put(OUT_MESSAGE, NOT_IN_PROD_VOS_GROUPS_MSG); - model.put(OUT_CONTACT_P, CONTACT_LANG_PROP_KEY); - model.put(CONTACT_MAIL, perunOidcConfig.getEmailContact()); - return "unapproved_spec"; - } - - @GetMapping(value = UNAPPROVED_NOT_IN_MANDATORY_VOS_GROUPS) - public String showUnapprovedNotInMandatoryVosGroups(HttpServletRequest req, Map<String, Object> model) { - ControllerUtils.setPageOptions(model, req, htmlClasses, perunOidcConfig); - - model.put(OUT_HEADER, NOT_IN_MANDATORY_VOS_GROUPS_HDR); - model.put(OUT_MESSAGE, NOT_IN_MANDATORY_VOS_GROUPS_MSG); - model.put(OUT_CONTACT_P, CONTACT_LANG_PROP_KEY); - model.put(CONTACT_MAIL, perunOidcConfig.getEmailContact()); - return "unapproved_spec"; - } - - @GetMapping(value = UNAPPROVED_NOT_LOGGED_IN) - public String showUnapprovedNotLoggedIn(HttpServletRequest req, Map<String, Object> model) { - ControllerUtils.setPageOptions(model, req, htmlClasses, perunOidcConfig); - - model.put(OUT_HEADER, NOT_LOGGED_IN_HDR); - model.put(OUT_MESSAGE, NOT_LOGGED_IN_MSG); - model.put(OUT_CONTACT_P, CONTACT_LANG_PROP_KEY); - model.put(CONTACT_MAIL, perunOidcConfig.getEmailContact()); - return "unapproved_spec"; - } - - - private String loadSessionTranslationKey(HttpSession sess, String key, String fallbackValue) { - if (sess != null && StringUtils.hasText((String) sess.getAttribute(key))) { - return (String) sess.getAttribute(key); - } - return fallbackValue; - } - -} diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/PerunUnapprovedRegistrationController.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/PerunUnapprovedRegistrationController.java deleted file mode 100644 index 3fab8a35b..000000000 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/PerunUnapprovedRegistrationController.java +++ /dev/null @@ -1,176 +0,0 @@ -package cz.muni.ics.oidc.web.controllers; - -import cz.muni.ics.oauth2.model.ClientDetailsEntity; -import cz.muni.ics.oauth2.service.ClientDetailsEntityService; -import cz.muni.ics.oidc.models.Facility; -import cz.muni.ics.oidc.models.Group; -import cz.muni.ics.oidc.models.PerunAttributeValue; -import cz.muni.ics.oidc.models.Vo; -import cz.muni.ics.oidc.server.adapters.PerunAdapter; -import cz.muni.ics.oidc.server.configurations.FacilityAttrsConfig; -import cz.muni.ics.oidc.server.configurations.PerunOidcConfig; -import cz.muni.ics.oidc.web.WebHtmlClasses; -import cz.muni.ics.openid.connect.view.HttpCodeView; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; - -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -/** - * Controller for the unapproved page which offers registration. - * - * @author Dominik Frantisek Bucik <bucik@ics.muni.cz> - */ -@Controller -@Slf4j -public class PerunUnapprovedRegistrationController { - - public static final String REGISTRATION_FORM_MAPPING = "/regForm"; - public static final String REGISTRATION_FORM_SUBMIT_MAPPING = "/regForm/submit"; - public static final String REGISTRATION_CONTINUE_MAPPING = "/regForm/continue"; - - @Autowired - private ClientDetailsEntityService clientService; - - @Autowired - private PerunAdapter perunAdapter; - - @Autowired - private FacilityAttrsConfig facilityAttrsConfig; - - @Autowired - private PerunOidcConfig perunOidcConfig; - - @Autowired - private WebHtmlClasses htmlClasses; - - @GetMapping(value = REGISTRATION_FORM_MAPPING) - public String showRegistrationForm(Map<String, Object> model, ServletRequest req, ServletResponse res, - @RequestParam("client_id") String clientId, - @RequestParam("facility_id") Long facilityId, - @RequestParam("user_id") Long userId) - { - HttpServletRequest request = (HttpServletRequest) req; - HttpServletResponse response = (HttpServletResponse) res; - ClientDetailsEntity client; - - try { - client = clientService.loadClientByClientId(clientId); - } catch (OAuth2Exception e) { - log.error("confirmAccess: OAuth2Exception was thrown when attempting to load client", e); - model.put(HttpCodeView.CODE, HttpStatus.NOT_FOUND); - return HttpCodeView.VIEWNAME; - } catch (IllegalArgumentException e) { - log.error("confirmAccess: IllegalArgumentException was thrown when attempting to load client", e); - model.put(HttpCodeView.CODE, HttpStatus.BAD_REQUEST); - return HttpCodeView.VIEWNAME; - } - - if (client == null) { - log.error("confirmAccess: could not find client {}", clientId); - model.put(HttpCodeView.CODE, HttpStatus.NOT_FOUND); - return HttpCodeView.VIEWNAME; - } - - Facility facility = perunAdapter.getFacilityByClientId(clientId); - Map<String, PerunAttributeValue> facilityAttributes = perunAdapter.getFacilityAttributeValues(facility, - facilityAttrsConfig.getMembershipAttrNames()); - List<String> voShortNames = facilityAttributes.get(facilityAttrsConfig.getVoShortNamesAttr()).valueAsList(); - Map<Vo, List<Group>> groupsForRegistration = perunAdapter.getAdapterRpc() - .getGroupsForRegistration(facility, userId, voShortNames); - - if (groupsForRegistration.isEmpty()) { - String redirectUrl = ControllerUtils.createRedirectUrl(perunOidcConfig.getConfigBean().getIssuer(), - PerunUnapprovedController.UNAPPROVED_MAPPING, Collections.singletonMap("client_id", clientId)); - response.reset(); - response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); - response.setHeader("Location", redirectUrl); - return null; - } else if (groupsForRegistration.keySet().size() == 1) { - for (Map.Entry<Vo, List<Group>> entry: groupsForRegistration.entrySet()) { - // no other way how to extract the first item (as it is the only) - List<Group> groupList = groupsForRegistration.get(entry.getKey()); - if (groupList.size() == 1) { - Group group = groupList.get(0); - String redirectUrl = createRegistrarUrl(entry.getKey(), group.getName()); - response.reset(); - response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); - response.setHeader("Location", redirectUrl); - return null; - } - } - } - - ControllerUtils.setPageOptions(model, request, htmlClasses, perunOidcConfig); - model.put("client", client); - model.put("facilityId", facilityId); - model.put("action", buildActionUrl(request)); - model.put("groupsForRegistration", groupsForRegistration); - model.put("page", "regForm"); - return "registrationForm"; - } - - @GetMapping(value = REGISTRATION_FORM_SUBMIT_MAPPING) - public void processRegistrationForm(@RequestParam("selectedGroup") String groupName, - @RequestParam("selectedVo") String voName, - ServletResponse res) throws IOException { - HttpServletResponse request = (HttpServletResponse) res; - - groupName = groupName.split(":", 2)[1]; - - String redirectUrl = createRegistrarUrl(voName, groupName); - - request.sendRedirect(redirectUrl); - } - - @GetMapping(value = REGISTRATION_CONTINUE_MAPPING) - public String showContinuePage(Map<String, Object> model, ServletRequest req, - @RequestParam("client_id") String clientId, - @RequestParam("facility_id") Long facilityId, - @RequestParam("user_id") Long userId) - { - HttpServletRequest request = (HttpServletRequest) req; - - model.put("page", "regContinue"); - model.put("client_id", clientId); - model.put("facility_id", facilityId); - model.put("user_id", userId); - model.put("action", request.getRequestURL().toString() - .replace(REGISTRATION_CONTINUE_MAPPING, REGISTRATION_FORM_MAPPING)); - ControllerUtils.setPageOptions(model, request, htmlClasses, perunOidcConfig); - return "registrationFormContinue"; - } - - private String createRegistrarUrl(Vo vo, String groupName) { - return createRegistrarUrl(vo.getShortName(), groupName); - } - - private String createRegistrarUrl(String vohortName, String groupName) { - String redirectUrl = perunOidcConfig.getRegistrarUrl().concat("?vo=").concat(vohortName); - if (groupName != null && !groupName.isEmpty() && !groupName.equalsIgnoreCase("members")) { - redirectUrl = redirectUrl.concat("&group=").concat(groupName); - } - - return redirectUrl; - } - - private String buildActionUrl(HttpServletRequest request) { - int startIndex = request.getRequestURL().lastIndexOf(REGISTRATION_FORM_MAPPING); - int length = request.getRequestURL().length(); - return request.getRequestURL().delete(startIndex, length) - .append(REGISTRATION_FORM_SUBMIT_MAPPING).toString(); - } - -} diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/PerunUnauthorizedController.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/PerunUnauthorizedController.java new file mode 100644 index 000000000..44f1574ba --- /dev/null +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/PerunUnauthorizedController.java @@ -0,0 +1,324 @@ +package cz.muni.ics.oidc.web.controllers; + +import cz.muni.ics.oauth2.model.ClientDetailsEntity; +import cz.muni.ics.oidc.PerunConstants; +import cz.muni.ics.oidc.RedirectUtils; +import cz.muni.ics.oidc.models.Facility; +import cz.muni.ics.oidc.models.Group; +import cz.muni.ics.oidc.models.PerunAttributeValue; +import cz.muni.ics.oidc.models.PerunUser; +import cz.muni.ics.oidc.models.Vo; +import cz.muni.ics.oidc.server.adapters.PerunAdapter; +import cz.muni.ics.oidc.server.configurations.FacilityAttrsConfig; +import cz.muni.ics.oidc.server.configurations.PerunOidcConfig; +import cz.muni.ics.oidc.web.WebHtmlClasses; +import cz.muni.ics.openid.connect.view.HttpCodeView; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + + +/** + * Ctonroller for the unauthorized page. + * + * @author Dominik Frantisek Bucik <bucik@ics.muni.cz> + */ +@Controller +@Slf4j +public class PerunUnauthorizedController { + + public static final String UNAUTHORIZED_MAPPING = "/unauthorized"; + public static final String UNAUTHORIZED_SPECIFIC_MAPPING = "/unauthorizedSpec"; + public static final String UNAUTHORIZED_IS_ELIGIBLE_MAPPING = "/unauthorizedIsEligible"; + public static final String UNAUTHORIZED_ENSURE_VO_MAPPING = "/unauthorizedEnsureVo"; + public static final String UNAUTHORIZED_ENSURE_VO_REDIRECT_NOTIFY_MAPPING = "/unauthorizedEnsureVoRedirectNotify"; + public static final String UNAUTHORIZED_AUTHORIZATION_MAPPING = "/unauthorizedAuthorization"; + public static final String UNAUTHORIZED_NOT_IN_ENV_VOS_GROUPS_MAPPING = "/unauthorizedEnvVosGroups"; + public static final String UNAUTHORIZED_NOT_LOGGED_IN_MAPPING = "/unauthorizedNotLoggedIn"; + + public static final String UNAUTHORIZED_REGISTER_CHOOSE_VO_GROUP_MAPPING = "/unauthorizedRegisterChooseVoGroup"; + public static final String UNAUTHORIZED_REGISTER_NOTIFY_ACTION_REQUIRED_MAPPING = "/unauthorizedRegisterNotifyActionRequired"; + + // SESSION ATTRIBUTES FOR PASSING DATA + + public static final String SESS_ATTR_REGISTRATION_UNITS = "registrationUnits"; + public static final String SESS_ATTR_CLIENT = "client"; + + public static final String SESS_ATTR_TARGET = "target"; + + public static final String SESS_ATTR_USER = "logged_user"; + public static final String SESS_ATTR_FACILITY = "client_facility"; + + public static final String SESS_ATTR_HEADER_TRANSLATION = "header_translation"; + public static final String SESS_ATTR_TEXT_TRANSLATION = "text_translation"; + public static final String SESS_ATTR_BUTTON_TRANSLATION = "button_translation"; + public static final String SESS_ATTR_CONTACT_TRANSLATION = "contact_translation"; + public static final String SESS_ATTR_HEADER = "header"; + public static final String SESS_ATTR_MESSAGE = "message"; + + // MODEL ATTRIBUTES + private static final String MODEL_REG_URLS = "registrationUrls"; + private static final String MODEL_ATTR_CLIENT = "client"; + private static final String MODEL_ATTR_GROUPS_FOR_REGISTRATION = "groupsForRegistration"; + private static final String MODEL_ATTR_PERUN_REGISTRAR_URL = "registrarUrl"; + private static final String MODEL_ATTR_TRANSL_HEADER = "outHeader"; + private static final String MODEL_ATTR_TRANSL_MESSAGE = "outMessage"; + private static final String MODEL_ATTR_TANSL_SUBMIT_BTN = "outButton"; + private static final String MODEL_ATTR_TRANSL_CONTACT_P = "outContactP"; + private static final String MODEL_ATTR_TARGET = "target"; + private static final String MODEL_ATTR_AAI_CONTACT_ADDRESS = "contactMail"; + + // TRANSLATION KEYS + + private static final String AUTHORIZATION_HDR = "403_authorization_hdr"; + private static final String AUTHORIZATION_MSG = "403_authorization_msg"; + + private static final String NOT_LOGGED_IN_HDR = "403_not_logged_in_hdr"; + private static final String NOT_LOGGED_IN_MSG = "403_not_logged_in_msg"; + + // VIEWS + public static final String VIEW_UNAUTHORIZED_SPEC = "unauthorized_spec"; + + private final PerunOidcConfig perunOidcConfig; + private final WebHtmlClasses htmlClasses; + private final PerunAdapter perunAdapter; + private final FacilityAttrsConfig facilityAttrsConfig; + + public PerunUnauthorizedController(PerunOidcConfig perunOidcConfig, + WebHtmlClasses htmlClasses, + PerunAdapter perunAdapter, + FacilityAttrsConfig facilityAttrsConfig) + { + this.perunOidcConfig = perunOidcConfig; + this.htmlClasses = htmlClasses; + this.perunAdapter = perunAdapter; + this.facilityAttrsConfig = facilityAttrsConfig; + } + + @GetMapping(value = UNAUTHORIZED_MAPPING) + public String showUnauthorized(HttpServletRequest req, Map<String, Object> model) { + HttpSession sess = req.getSession(); + + ClientDetailsEntity client = (ClientDetailsEntity) sess.getAttribute(SESS_ATTR_CLIENT); + + if (client == null) { + model.put(HttpCodeView.CODE, HttpStatus.INTERNAL_SERVER_ERROR); + return HttpCodeView.VIEWNAME; + } + + ControllerUtils.setPageOptions(model, req, htmlClasses, perunOidcConfig); + model.put(MODEL_ATTR_CLIENT, client); + return "unauthorized"; + } + + @GetMapping(value = UNAUTHORIZED_SPECIFIC_MAPPING) + public String showUnauthorizedSpec(HttpServletRequest req, Map<String, Object> model) + { + ControllerUtils.setPageOptions(model, req, htmlClasses, perunOidcConfig); + + HttpSession sess = req.getSession(); + String header = (String) sess.getAttribute(SESS_ATTR_HEADER); + String message = (String) sess.getAttribute(SESS_ATTR_MESSAGE); + + model.put(MODEL_ATTR_TRANSL_HEADER, header); + model.put(MODEL_ATTR_TRANSL_MESSAGE, message); + model.put(MODEL_ATTR_AAI_CONTACT_ADDRESS, perunOidcConfig.getEmailContact()); + return VIEW_UNAUTHORIZED_SPEC; + } + + @GetMapping(value = UNAUTHORIZED_IS_ELIGIBLE_MAPPING) + public String showUnauthorizedIsEligible(HttpServletRequest req, HttpSession sess, Map<String, Object> model) { + ControllerUtils.setPageOptions(model, req, htmlClasses, perunOidcConfig); + + String header = (String) sess.getAttribute(SESS_ATTR_HEADER_TRANSLATION); + String message = (String) sess.getAttribute(SESS_ATTR_TEXT_TRANSLATION); + String button = (String) sess.getAttribute(SESS_ATTR_BUTTON_TRANSLATION); + String contactP = (String) sess.getAttribute(SESS_ATTR_CONTACT_TRANSLATION); + String targetUrl = (String) sess.getAttribute(SESS_ATTR_TARGET); + ClientDetailsEntity client = (ClientDetailsEntity) sess.getAttribute(SESS_ATTR_CLIENT); + + model.put(MODEL_ATTR_TRANSL_HEADER, header); + model.put(MODEL_ATTR_TRANSL_MESSAGE, message); + model.put(MODEL_ATTR_TANSL_SUBMIT_BTN, button); + model.put(MODEL_ATTR_TRANSL_CONTACT_P, contactP); + model.put(MODEL_ATTR_AAI_CONTACT_ADDRESS, perunOidcConfig.getEmailContact()); + model.put(MODEL_ATTR_CLIENT, client); + model.put(MODEL_ATTR_TARGET, targetUrl); + return "unauthorized_is_eligible"; + } + + @GetMapping(value = UNAUTHORIZED_ENSURE_VO_MAPPING) + public String showUnauthorizedEnsureVo(HttpServletRequest req, HttpSession sess, Map<String, Object> model) { + ControllerUtils.setPageOptions(model, req, htmlClasses, perunOidcConfig); + + model.put(MODEL_ATTR_CLIENT, sess.getAttribute(SESS_ATTR_CLIENT)); + model.put(MODEL_ATTR_AAI_CONTACT_ADDRESS, perunOidcConfig.getEmailContact()); + + return VIEW_UNAUTHORIZED_SPEC; + } + + @GetMapping(value = UNAUTHORIZED_ENSURE_VO_REDIRECT_NOTIFY_MAPPING) + public String showUnauthorizedEnsureVoRedirectNotify(HttpServletRequest req, + HttpSession sess, + Map<String, Object> model) + { + String target = (String) sess.getAttribute(SESS_ATTR_TARGET); + model.put(MODEL_ATTR_TARGET, target); + ControllerUtils.setPageOptions(model, req, htmlClasses, perunOidcConfig); + return "unauthorized_ensure_vo_member_notify_redirect"; + } + + @GetMapping(value = UNAUTHORIZED_AUTHORIZATION_MAPPING) + public String showUnauthorizedAuthorization(HttpServletRequest req, HttpSession sess, Map<String, Object> model) { + ControllerUtils.setPageOptions(model, req, htmlClasses, perunOidcConfig); + ClientDetailsEntity client = (ClientDetailsEntity) sess.getAttribute(SESS_ATTR_CLIENT); + + model.put(MODEL_ATTR_CLIENT, client); + model.put(MODEL_ATTR_TRANSL_HEADER, AUTHORIZATION_HDR); + model.put(MODEL_ATTR_TRANSL_MESSAGE, AUTHORIZATION_MSG); + model.put(MODEL_ATTR_AAI_CONTACT_ADDRESS, perunOidcConfig.getEmailContact()); + return VIEW_UNAUTHORIZED_SPEC; + } + + @GetMapping(value = UNAUTHORIZED_NOT_IN_ENV_VOS_GROUPS_MAPPING) + public String showUnauthorizedNotInEnvUnits(HttpServletRequest req, Map<String, Object> model) { + ControllerUtils.setPageOptions(model, req, htmlClasses, perunOidcConfig); + + HttpSession sess = req.getSession(); + + Map<Vo, Set<Group>> registrationUnits = (Map<Vo, Set<Group>>) sess.getAttribute(SESS_ATTR_REGISTRATION_UNITS); + ClientDetailsEntity client = (ClientDetailsEntity) sess.getAttribute(SESS_ATTR_CLIENT); + + Map<String, String> urls = new HashMap<>(); + for (Map.Entry<Vo, Set<Group>> entry : registrationUnits.entrySet()) { + Vo vo = entry.getKey(); + if (entry.getValue().isEmpty()) { + String url = ControllerUtils.createUrl( + perunOidcConfig.getRegistrarUrl(), Map.of("vo", vo.getShortName()) + ); + urls.put(url, vo.getName()); + } else { + for (Group group : entry.getValue()) { + String url = ControllerUtils.createUrl( + perunOidcConfig.getRegistrarUrl(), + Map.of("vo", vo.getShortName(), "group", group.getName()) + ); + urls.put(url, group.getName() + "(" + group.getDescription() + ")"); + } + } + } + + model.put(MODEL_REG_URLS, urls); + model.put(MODEL_ATTR_CLIENT, client); + return "unauthorized_not_in_env_units"; + } + + @GetMapping(value = UNAUTHORIZED_NOT_LOGGED_IN_MAPPING) + public String showUnauthorizedNotLoggedIn(HttpServletRequest req, Map<String, Object> model) { + ControllerUtils.setPageOptions(model, req, htmlClasses, perunOidcConfig); + + model.put(MODEL_ATTR_TRANSL_HEADER, NOT_LOGGED_IN_HDR); + model.put(MODEL_ATTR_TRANSL_MESSAGE, NOT_LOGGED_IN_MSG); + model.put(MODEL_ATTR_AAI_CONTACT_ADDRESS, perunOidcConfig.getEmailContact()); + return VIEW_UNAUTHORIZED_SPEC; + } + + @GetMapping(value = UNAUTHORIZED_REGISTER_CHOOSE_VO_GROUP_MAPPING) + public String unauthorizedRegisterChooseVoGroup(HttpServletRequest req, + HttpServletResponse res, + HttpSession sess, + Map<String, Object> model) + { + ClientDetailsEntity client = (ClientDetailsEntity) sess.getAttribute(SESS_ATTR_CLIENT); + Facility facility = (Facility) sess.getAttribute(SESS_ATTR_FACILITY); + PerunUser user = (PerunUser) sess.getAttribute(SESS_ATTR_USER); + + if (client == null) { + log.error("confirmAccess: could not find client in session"); + return error(model); + } else if (facility == null) { + log.error("confirmAccess: could not find facility in session"); + return error(model); + } else if (user == null) { + log.error("confirmAccess: could not find user in session"); + return error(model); + } + + Map<String, PerunAttributeValue> facilityAttributes = perunAdapter.getFacilityAttributeValues(facility, + facilityAttrsConfig.getMembershipAttrNames()); + + List<String> voShortNames = facilityAttributes.get(facilityAttrsConfig.getVoShortNamesAttr()).valueAsList(); + Map<Vo, List<Group>> groupsForRegistration = perunAdapter.getAdapterRpc() + .getGroupsForRegistration(facility, user.getId(), voShortNames); + + if (groupsForRegistration.isEmpty()) { + log.debug("Redirecting user '{}' to the internal page informing about unauthorized access", user); + Map<String, Object> sessAttributes = new HashMap<>(); + sessAttributes.put(PerunUnauthorizedController.SESS_ATTR_CLIENT, client); + RedirectUtils.redirectInternal(req, res, perunOidcConfig, PerunUnauthorizedController.UNAUTHORIZED_AUTHORIZATION_MAPPING, sessAttributes); + return null; + } else if (groupsForRegistration.keySet().size() == 1) { + for (Map.Entry<Vo, List<Group>> entry: groupsForRegistration.entrySet()) { + // no other way how to extract the first item (as it is the only) + List<Group> groupList = groupsForRegistration.get(entry.getKey()); + if (groupList.size() == 1) { + Group group = groupList.get(0); + String redirectUrl = createRegistrarUrl(entry.getKey(), group.getName()); + RedirectUtils.redirectExternal(res, redirectUrl); + return null; + } + } + } + + model.put(MODEL_ATTR_CLIENT, client); + model.put(MODEL_ATTR_GROUPS_FOR_REGISTRATION, groupsForRegistration); + model.put(MODEL_ATTR_PERUN_REGISTRAR_URL, perunOidcConfig.getRegistrarUrl()); + ControllerUtils.setPageOptions(model, req, htmlClasses, perunOidcConfig, "unauthorized_register_choose_vo_group"); + return "unauthorized_register_choose_vo_group"; + } + + @GetMapping(value = UNAUTHORIZED_REGISTER_NOTIFY_ACTION_REQUIRED_MAPPING) + public String unauthorizedRegisterNotifyActionRequired(HttpServletRequest req, + HttpSession sess, + Map<String, Object> model) + { + ClientDetailsEntity client = (ClientDetailsEntity) sess.getAttribute(SESS_ATTR_CLIENT); + if (client == null) { + log.error("confirmAccess: could not find client in session"); + return error(model); + } + + model.put(MODEL_ATTR_CLIENT, client); + ControllerUtils.setPageOptions(model, req, htmlClasses, perunOidcConfig, "unauthorized_register_notify_action_required"); + return "unauthorized_register_notify_action_required"; + } + + private String createRegistrarUrl(Vo vo, String groupName) { + return createRegistrarUrl(vo.getShortName(), groupName); + } + + private String createRegistrarUrl(String voShortName, String groupName) { + Map<String, String> params = new HashMap<>(); + params.put(PerunConstants.REGISTRAR_PARAM_VO, voShortName); + if (groupName != null && !groupName.isEmpty() && !groupName.equalsIgnoreCase(PerunConstants.GROUP_NAME_MEMBERS)) { + params.put(PerunConstants.REGISTRAR_PARAM_GROUP, groupName); + } + + return ControllerUtils.createUrl(perunOidcConfig.getRegistrarUrl(), params); + } + + private String error(Map<String, Object> model) { + model.put(HttpCodeView.CODE, HttpStatus.INTERNAL_SERVER_ERROR); + return HttpCodeView.VIEWNAME; + } + +} diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/RegistrationController.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/RegistrationController.java deleted file mode 100644 index 68bedde97..000000000 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/RegistrationController.java +++ /dev/null @@ -1,42 +0,0 @@ -package cz.muni.ics.oidc.web.controllers; - -import cz.muni.ics.oidc.server.configurations.PerunOidcConfig; -import cz.muni.ics.oidc.web.WebHtmlClasses; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; - -import javax.servlet.http.HttpServletRequest; -import java.util.Map; - -/** - * Controller for the unapproved page which offers registration. - * - * @author Dominik Frantisek Bucik <bucik@ics.muni.cz> - */ -@Controller -@Slf4j -public class RegistrationController { - - public static final String PARAM_TARGET = "target"; - - public static final String CONTINUE_DIRECT_MAPPING = "/continueDirect"; - - @Autowired - private PerunOidcConfig perunOidcConfig; - - @Autowired - private WebHtmlClasses htmlClasses; - - @GetMapping(value = CONTINUE_DIRECT_MAPPING, params = { PARAM_TARGET }) - public String showRegistrationForm(HttpServletRequest req, Map<String, Object> model, - @RequestParam(PARAM_TARGET) String target) - { - model.put(PARAM_TARGET, target); - ControllerUtils.setPageOptions(model, req, htmlClasses, perunOidcConfig); - return "registrationFormContinue"; - } - -} diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/TestSpWarningController.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/TestSpWarningController.java new file mode 100644 index 000000000..db83230c5 --- /dev/null +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/web/controllers/TestSpWarningController.java @@ -0,0 +1,63 @@ +package cz.muni.ics.oidc.web.controllers; + +import cz.muni.ics.oidc.server.configurations.PerunOidcConfig; +import cz.muni.ics.oidc.web.WebHtmlClasses; +import cz.muni.ics.openid.connect.view.HttpCodeView; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import java.util.Map; + +/** + * Controller for IS TEST SP pages. + * + * @author Pavol Pluta <pavol.pluta1@gmail.com> + */ +@Controller +@Slf4j +public class TestSpWarningController { + + public static final String MAPPING = "/testSp"; + public static final String SESS_ATTR_TARGET = "target"; + public static final String SESS_ATTR_IS_TEST_SP_APPROVED = "isTestSpApprovedSession"; + + private final WebHtmlClasses htmlClasses; + private final PerunOidcConfig perunOidcConfig; + + @Autowired + public TestSpWarningController(WebHtmlClasses htmlClasses, PerunOidcConfig perunOidcConfig) { + this.htmlClasses = htmlClasses; + this.perunOidcConfig = perunOidcConfig; + } + + @GetMapping(value = MAPPING) + public String showTestSpWarning(HttpServletRequest req, + Map<String, Object> model) + { + ControllerUtils.setPageOptions(model, req, htmlClasses, perunOidcConfig); + return "test_rp_warning"; + } + + @PostMapping(value = MAPPING) + public String showTestSpWarningSubmit(HttpSession sess, Map<String, Object> model) + { + if (sess != null) { + sess.setAttribute(SESS_ATTR_IS_TEST_SP_APPROVED, true); + String target = (String) sess.getAttribute(SESS_ATTR_TARGET); + if (target != null) { + return "redirect:" + target; + } + } + log.debug("showTestSpWarningSubmit: missing session attribute TARGET, cannot redirect to original req"); + model.put(HttpCodeView.CODE, HttpStatus.INTERNAL_SERVER_ERROR); + return HttpCodeView.VIEWNAME; + + } + +} -- GitLab