From c89418d9f5b76085c1ea3ea6be8c5e93d14a1626 Mon Sep 17 00:00:00 2001 From: milanmajchrak Date: Wed, 2 Oct 2024 16:10:17 +0200 Subject: [PATCH 1/6] Load netid from more than one header. authentication-shibboleth.netid-header could be list, not only single value --- .../clarin/ClarinShibAuthentication.java | 67 ++++---- .../authenticate/clarin/ShibHeaders.java | 7 +- .../test/data/dspaceFolder/config/local.cfg | 2 +- .../ClarinShibbolethLoginFilterIT.java | 147 ++++++++++-------- .../modules/authentication-shibboleth.cfg | 2 +- 5 files changed, 130 insertions(+), 95 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java b/dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java index 822543d08c80..5fe2a34c2d33 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java @@ -11,6 +11,7 @@ import java.net.URLEncoder; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; @@ -25,7 +26,6 @@ import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.dspace.app.util.Util; import org.dspace.authenticate.AuthenticationMethod; import org.dspace.authenticate.factory.AuthenticateServiceFactory; import org.dspace.authorize.AuthorizeException; @@ -247,15 +247,16 @@ public int authenticate(Context context, String username, String password, // Should we auto register new users. boolean autoRegister = configurationService.getBooleanProperty("authentication-shibboleth.autoregister", true); + String[] netidHeaders = configurationService.getArrayProperty("authentication-shibboleth.netid-header"); // Four steps to authenticate a user try { // Step 1: Identify User - EPerson eperson = findEPerson(context, request); + EPerson eperson = findEPerson(context, request, netidHeaders); // Step 2: Register New User, if necessary if (eperson == null && autoRegister && !isDuplicateUser) { - eperson = registerNewEPerson(context, request); + eperson = registerNewEPerson(context, request, netidHeaders); } if (eperson == null) { @@ -263,7 +264,7 @@ public int authenticate(Context context, String username, String password, } // Step 3: Update User's Metadata - updateEPerson(context, request, eperson); + updateEPerson(context, request, eperson, netidHeaders); // Step 4: Log the user in. context.setCurrentUser(eperson); @@ -540,11 +541,11 @@ public static boolean isEnabled() { * @throws SQLException if database error * @throws AuthorizeException if authorization error */ - protected EPerson findEPerson(Context context, HttpServletRequest request) throws SQLException, AuthorizeException { + protected EPerson findEPerson(Context context, HttpServletRequest request, String[] netidHeaders) + throws SQLException { boolean isUsingTomcatUser = configurationService .getBooleanProperty("authentication-shibboleth.email-use-tomcat-remote-user"); - String netidHeader = configurationService.getProperty("authentication-shibboleth.netid-header"); String emailHeader = configurationService.getProperty("authentication-shibboleth.email-header"); EPerson eperson = null; @@ -554,21 +555,22 @@ protected EPerson findEPerson(Context context, HttpServletRequest request) throw // 1) First, look for a netid header. - if (netidHeader != null) { - String org = shibheaders.get_idp(); - String netid = Util.formatNetId(findSingleAttribute(request, netidHeader), org); - if (StringUtils.isEmpty(netid)) { - netid = shibheaders.get_single(netidHeader); - } + if (netidHeaders != null) { + // Go through all the netid headers and try to find a user. It could be e.g., `eppn`, `persistent-id`,.. + for (String netidHeader : netidHeaders) { + netidHeader = netidHeader.trim(); + String netid = shibheaders.get_single(netidHeader); + if (netid == null) { + continue; + } - if (netid != null) { foundNetID = true; eperson = ePersonService.findByNetid(context, netid); if (eperson == null) { log.info( - "Unable to identify EPerson based upon Shibboleth netid header: '" + netidHeader + "'='" + - netid + "'."); + "Unable to identify EPerson based upon Shibboleth netid header: '" + netidHeader + + "'='" + netid + "'."); } else { log.debug( "Identified EPerson based upon Shibboleth netid header: '" + netidHeader + "'='" + @@ -677,11 +679,10 @@ protected EPerson findEPerson(Context context, HttpServletRequest request) throw * @throws SQLException if database error * @throws AuthorizeException if authorization error */ - protected EPerson registerNewEPerson(Context context, HttpServletRequest request) + protected EPerson registerNewEPerson(Context context, HttpServletRequest request, String[] netidHeaders) throws SQLException, AuthorizeException { // Header names - String netidHeader = configurationService.getProperty("authentication-shibboleth.netid-header"); String emailHeader = configurationService.getProperty("authentication-shibboleth.email-header"); String fnameHeader = configurationService.getProperty("authentication-shibboleth.firstname-header"); String lnameHeader = configurationService.getProperty("authentication-shibboleth.lastname-header"); @@ -694,15 +695,12 @@ protected EPerson registerNewEPerson(Context context, HttpServletRequest request // CLARIN // Header values - String netid = Util.formatNetId(findSingleAttribute(request, netidHeader), org); + String netid = getFirstNetId(netidHeaders); String email = getEmailAcceptedOrNull(findSingleAttribute(request, emailHeader)); String fname = Headers.updateValueByCharset(findSingleAttribute(request, fnameHeader)); String lname = Headers.updateValueByCharset(findSingleAttribute(request, lnameHeader)); // If the values are not in the request headers try to retrieve it from `shibheaders`. - if (StringUtils.isEmpty(netid)) { - netid = shibheaders.get_single(netidHeader); - } if (StringUtils.isEmpty(email) && Objects.nonNull(clarinVerificationToken)) { email = clarinVerificationToken.getEmail(); } @@ -718,7 +716,7 @@ protected EPerson registerNewEPerson(Context context, HttpServletRequest request // don't have at least these three pieces of information then we fail. String message = "Unable to register new eperson because we are unable to find an email address along " + "with first and last name for the user.\n"; - message += " NetId Header: '" + netidHeader + "'='" + netid + "' (Optional) \n"; + message += " NetId Header: '" + Arrays.toString(netidHeaders) + "'='" + netid + "' (Optional) \n"; message += " Email Header: '" + emailHeader + "'='" + email + "' \n"; message += " First Name Header: '" + fnameHeader + "'='" + fname + "' \n"; message += " Last Name Header: '" + lnameHeader + "'='" + lname + "'"; @@ -807,24 +805,20 @@ protected EPerson registerNewEPerson(Context context, HttpServletRequest request * @throws SQLException if database error * @throws AuthorizeException if authorization error */ - protected void updateEPerson(Context context, HttpServletRequest request, EPerson eperson) + protected void updateEPerson(Context context, HttpServletRequest request, EPerson eperson, String[] netidHeaders) throws SQLException, AuthorizeException { // Header names & values - String netidHeader = configurationService.getProperty("authentication-shibboleth.netid-header"); String emailHeader = configurationService.getProperty("authentication-shibboleth.email-header"); String fnameHeader = configurationService.getProperty("authentication-shibboleth.firstname-header"); String lnameHeader = configurationService.getProperty("authentication-shibboleth.lastname-header"); - String netid = Util.formatNetId(findSingleAttribute(request, netidHeader), shibheaders.get_idp()); + String netid = getFirstNetId(netidHeaders); String email = getEmailAcceptedOrNull(findSingleAttribute(request, emailHeader)); String fname = Headers.updateValueByCharset(findSingleAttribute(request, fnameHeader)); String lname = Headers.updateValueByCharset(findSingleAttribute(request, lnameHeader)); // If the values are not in the request headers try to retrieve it from `shibheaders`. - if (StringUtils.isEmpty(netid)) { - netid = shibheaders.get_single(netidHeader); - } if (StringUtils.isEmpty(email) && Objects.nonNull(clarinVerificationToken)) { email = clarinVerificationToken.getEmail(); } @@ -1338,5 +1332,22 @@ public String getEmailAcceptedOrNull(String email) { } return email; } + + + /** + * Get the first netid from the list of netid headers. E.g., eppn, persistent-id,... + * @param netidHeaders list of netid headers loaded from the configuration `authentication-shibboleth.netid-header` + */ + public String getFirstNetId(String[] netidHeaders) { + for (String netidHeader : netidHeaders) { + netidHeader = netidHeader.trim(); + String netid = shibheaders.get_single(netidHeader); + if (netid != null) { + //When creating use first match (eppn before targeted-id) + return netid; + } + } + return null; + } } diff --git a/dspace-api/src/main/java/org/dspace/authenticate/clarin/ShibHeaders.java b/dspace-api/src/main/java/org/dspace/authenticate/clarin/ShibHeaders.java index 65897087302e..84ae41b4fa6c 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/clarin/ShibHeaders.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/clarin/ShibHeaders.java @@ -14,6 +14,7 @@ import java.util.Map; import javax.servlet.http.HttpServletRequest; +import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -32,7 +33,7 @@ public class ShibHeaders { // constants // private static final String header_separator_ = ";"; - private String netIdHeader = ""; + private String[] netIdHeaders = null; ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService(); // variables @@ -105,7 +106,7 @@ public String get_single(String name) { List values = get(name); if (values != null && !values.isEmpty()) { // Format netId - if (StringUtils.equals(name, this.netIdHeader)) { + if (ArrayUtils.contains(this.netIdHeaders, name)) { return Util.formatNetId(values.get(0), this.get_idp()); } return values.get(0); @@ -150,6 +151,6 @@ public void log_headers() { } private void initializeNetIdHeader() { - this.netIdHeader = configurationService.getProperty("authentication-shibboleth.netid-header"); + this.netIdHeaders = configurationService.getArrayProperty("authentication-shibboleth.netid-header"); } } diff --git a/dspace-api/src/test/data/dspaceFolder/config/local.cfg b/dspace-api/src/test/data/dspaceFolder/config/local.cfg index cc9ccb26bbb2..1027d5bd93b7 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/local.cfg +++ b/dspace-api/src/test/data/dspaceFolder/config/local.cfg @@ -219,7 +219,7 @@ featured.service.teitok.description = A web-based platform for viewing, creating ##### Shibboleth ##### -authentication-shibboleth.netid-header = SHIB-NETID +authentication-shibboleth.netid-header = SHIB-NETID,eppn,persistent-id authentication-shibboleth.email-header = SHIB-MAIL authentication-shibboleth.firstname-header = SHIB-GIVENNAME authentication-shibboleth.lastname-header = SHIB-SURNAME diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ClarinShibbolethLoginFilterIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ClarinShibbolethLoginFilterIT.java index 8b62e95bed79..6f601065b3c6 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ClarinShibbolethLoginFilterIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ClarinShibbolethLoginFilterIT.java @@ -9,6 +9,7 @@ import static org.dspace.app.rest.security.ShibbolethLoginFilterIT.PASS_ONLY; import static org.dspace.app.rest.security.clarin.ClarinShibbolethLoginFilter.VERIFICATION_TOKEN_HEADER; +import static org.dspace.rdf.negotiation.MediaRange.token; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -19,6 +20,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -53,8 +55,12 @@ public class ClarinShibbolethLoginFilterIT extends AbstractControllerIntegrationTest { public static final String[] SHIB_ONLY = {"org.dspace.authenticate.clarin.ClarinShibAuthentication"}; + private static final String NET_ID_EPPN_HEADER = "eppn"; + private static final String NET_ID_PERSISTENT_ID = "persistent-id"; private static final String NET_ID_TEST_EPERSON = "123456789"; private static final String IDP_TEST_EPERSON = "Test Idp"; + private static final String KNIHOVNA_KUN_TEST_ZLUTOUCKY = "knihovna Kůň test Žluťoučký"; + private EPersonRest ePersonRest; private final String feature = CanChangePasswordFeature.NAME; @@ -183,10 +189,7 @@ public void userFillInEmailAndShouldBeRegisteredByVerificationToken() throws Exc .andExpect(status().isOk()); // Check if was created a user with such email and netid. - EPerson ePerson = ePersonService.findByNetid(context, Util.formatNetId(netId, idp)); - assertTrue(Objects.nonNull(ePerson)); - assertEquals(ePerson.getEmail(), email); - assertEquals(ePerson.getNetid(), Util.formatNetId(netId, idp)); + EPerson ePerson = checkUserWasCreated(netId, idp, email, null); // The user is registered now log him getClient().perform(post("/api/authn/shibboleth") @@ -207,7 +210,7 @@ public void userFillInEmailAndShouldBeRegisteredByVerificationToken() throws Exc .andExpect(status().isFound()); // Delete created eperson - clean after the test - EPersonBuilder.deleteEPerson(ePerson.getID()); + deleteShibbolethUser(ePerson); } @Test @@ -227,10 +230,7 @@ public void testShouldReturnDuplicateUserError() throws Exception { .andReturn().getResponse().getHeader("Authorization"); - getClient(token).perform(get("/api/authn/status")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.authenticated", is(true))) - .andExpect(jsonPath("$.authenticationMethod", is("shibboleth"))); + checkUserIsSignedIn(token); // Check if was created a user with such email and netid. EPerson ePerson = ePersonService.findByNetid(context, Util.formatNetId(netId, IDP_TEST_EPERSON)); @@ -264,10 +264,7 @@ public void testRedirectToGivenTrustedUrl() throws Exception { .andExpect(redirectedUrl("http://localhost:8080/server/api/authn/status")) .andReturn().getResponse().getHeader("Authorization"); - getClient(token).perform(get("/api/authn/status")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.authenticated", is(true))) - .andExpect(jsonPath("$.authenticationMethod", is("shibboleth"))); + checkUserIsSignedIn(token); getClient(token).perform( get("/api/authz/authorizations/search/object") @@ -299,11 +296,7 @@ public void patchPassword() throws Exception { .andExpect(redirectedUrl("http://localhost:4000")) .andReturn().getResponse().getHeader("Authorization"); - - getClient(token).perform(get("/api/authn/status")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.authenticated", is(true))) - .andExpect(jsonPath("$.authenticationMethod", is("shibboleth"))); + checkUserIsSignedIn(token); // updates password getClient(token).perform(patch("/api/eperson/epersons/" + clarinEperson.getID()) @@ -328,11 +321,7 @@ public void testRedirectToDefaultDspaceUrl() throws Exception { .andExpect(redirectedUrl("http://localhost:4000")) .andReturn().getResponse().getHeader("Authorization"); - - getClient(token).perform(get("/api/authn/status")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.authenticated", is(true))) - .andExpect(jsonPath("$.authenticationMethod", is("shibboleth"))); + checkUserIsSignedIn(token); getClient(token).perform( get("/api/authz/authorizations/search/object") @@ -463,28 +452,10 @@ public void testISOShibHeaders() throws Exception { .andExpect(redirectedUrl("http://localhost:4000")) .andReturn().getResponse().getHeader("Authorization"); - - getClient(token).perform(get("/api/authn/status")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.authenticated", is(true))) - .andExpect(jsonPath("$.authenticationMethod", is("shibboleth"))); - + checkUserIsSignedIn(token); // Check if was created a user with such email and netid. - EPerson ePerson = ePersonService.findByNetid(context, Util.formatNetId(testNetId, testIdp)); - assertTrue(Objects.nonNull(ePerson)); - assertEquals(ePerson.getEmail(), testMail); - assertEquals(ePerson.getFirstName(), "knihovna Kůň test Žluťoučký"); - - EPersonBuilder.deleteEPerson(ePerson.getID()); - - getClient(token).perform( - get("/api/authz/authorizations/search/object") - .param("embed", "feature") - .param("feature", feature) - .param("uri", utils.linkToSingleResource(ePersonRest, "self").getHref())) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.page.totalElements", is(0))) - .andExpect(jsonPath("$._embedded").doesNotExist()); + EPerson ePerson = checkUserWasCreated(testNetId, testIdp, testMail, KNIHOVNA_KUN_TEST_ZLUTOUCKY); + deleteShibbolethUser(ePerson); } @Test @@ -500,25 +471,89 @@ public void testUTF8ShibHeaders() throws Exception { .header("SHIB-MAIL", testMail) .header("Shib-Identity-Provider", testIdp) .header("SHIB-NETID", testNetId) - .header("SHIB-GIVENNAME", "knihovna Kůň test Žluťoučký")) + .header("SHIB-GIVENNAME", KNIHOVNA_KUN_TEST_ZLUTOUCKY)) + .andExpect(status().is3xxRedirection()) + .andExpect(redirectedUrl("http://localhost:4000")) + .andReturn().getResponse().getHeader("Authorization"); + + checkUserIsSignedIn(token); + // Check if was created a user with such email and netid. + EPerson ePerson = checkUserWasCreated(testNetId, testIdp, testMail, KNIHOVNA_KUN_TEST_ZLUTOUCKY); + deleteShibbolethUser(ePerson); + } + + @Test + public void testRedirectToMissingHeadersWithRedirectUrlParam() throws Exception { + String expectedMissingHeadersUrl = configurationService.getProperty("dspace.ui.url") + "/login/missing-headers"; + + getClient().perform(get("/api/authn/shibboleth") + .param("redirectUrl", "http://localhost:8080/server/api/authn/status") + .header("SHIB-MAIL", clarinEperson.getEmail()) + .header("SHIB-NETID", NET_ID_TEST_EPERSON)) + .andExpect(status().is3xxRedirection()) + .andExpect(redirectedUrl(expectedMissingHeadersUrl)); + } + + // eppn is set + @Test + public void testSuccessFullLoginEppnNetId() throws Exception { + String token = getClient().perform(get("/api/authn/shibboleth") + .header("Shib-Identity-Provider", IDP_TEST_EPERSON) + .header("SHIB-MAIL", clarinEperson.getEmail()) + .header(NET_ID_EPPN_HEADER, NET_ID_TEST_EPERSON)) .andExpect(status().is3xxRedirection()) .andExpect(redirectedUrl("http://localhost:4000")) .andReturn().getResponse().getHeader("Authorization"); + checkUserIsSignedIn(token); + + EPerson ePerson = checkUserWasCreated(NET_ID_TEST_EPERSON, IDP_TEST_EPERSON, clarinEperson.getEmail(), null); + deleteShibbolethUser(ePerson); + } + // persistent-id is set + @Test + public void testSuccessFullLoginPersistentIdNetId() throws Exception { + String token = getClient().perform(get("/api/authn/shibboleth") + .header("Shib-Identity-Provider", IDP_TEST_EPERSON) + .header("SHIB-MAIL", clarinEperson.getEmail()) + .header(NET_ID_PERSISTENT_ID, NET_ID_TEST_EPERSON)) + .andExpect(status().is3xxRedirection()) + .andExpect(redirectedUrl("http://localhost:4000")) + .andReturn().getResponse().getHeader("Authorization"); + + checkUserIsSignedIn(token); + EPerson ePerson = checkUserWasCreated(NET_ID_TEST_EPERSON, IDP_TEST_EPERSON, clarinEperson.getEmail(), null); + deleteShibbolethUser(ePerson); + } + + private EPerson checkUserWasCreated(String netIdValue, String idpValue, String email, String name) + throws SQLException { + // Check if was created a user with such email and netid. + EPerson ePerson = ePersonService.findByNetid(context, Util.formatNetId(netIdValue, idpValue)); + assertTrue(Objects.nonNull(ePerson)); + if (email != null) { + assertEquals(ePerson.getEmail(), email); + } + + if (name != null) { + assertEquals(ePerson.getFirstName(), name); + } + return ePerson; + } + + private void checkUserIsSignedIn(String token) throws Exception { getClient(token).perform(get("/api/authn/status")) .andExpect(status().isOk()) .andExpect(jsonPath("$.authenticated", is(true))) .andExpect(jsonPath("$.authenticationMethod", is("shibboleth"))); + } - // Check if was created a user with such email and netid. - EPerson ePerson = ePersonService.findByNetid(context, Util.formatNetId(testNetId, testIdp)); - assertTrue(Objects.nonNull(ePerson)); - assertEquals(ePerson.getEmail(), testMail); - assertEquals(ePerson.getFirstName(), "knihovna Kůň test Žluťoučký"); + private void deleteShibbolethUser(EPerson ePerson) throws Exception { EPersonBuilder.deleteEPerson(ePerson.getID()); + // Check it was correctly deleted getClient(token).perform( get("/api/authz/authorizations/search/object") .param("embed", "feature") @@ -528,16 +563,4 @@ public void testUTF8ShibHeaders() throws Exception { .andExpect(jsonPath("$.page.totalElements", is(0))) .andExpect(jsonPath("$._embedded").doesNotExist()); } - - @Test - public void testRedirectToMissingHeadersWithRedirectUrlParam() throws Exception { - String expectedMissingHeadersUrl = configurationService.getProperty("dspace.ui.url") + "/login/missing-headers"; - - getClient().perform(get("/api/authn/shibboleth") - .param("redirectUrl", "http://localhost:8080/server/api/authn/status") - .header("SHIB-MAIL", clarinEperson.getEmail()) - .header("SHIB-NETID", NET_ID_TEST_EPERSON)) - .andExpect(status().is3xxRedirection()) - .andExpect(redirectedUrl(expectedMissingHeadersUrl)); - } } diff --git a/dspace/config/modules/authentication-shibboleth.cfg b/dspace/config/modules/authentication-shibboleth.cfg index 7e176f71b718..62815a46d828 100644 --- a/dspace/config/modules/authentication-shibboleth.cfg +++ b/dspace/config/modules/authentication-shibboleth.cfg @@ -90,7 +90,7 @@ authentication-shibboleth.lazysession.secure = true # Authentication headers for Mail, NetID, and Tomcat's Remote User. # Supply all parameters possible. -authentication-shibboleth.netid-header = eppn +authentication-shibboleth.netid-header = eppn,persistent-id authentication-shibboleth.email-header = mail authentication-shibboleth.email-use-tomcat-remote-user = false From 773c79c2a57d24ad2914c1e918c228508d5f5856 Mon Sep 17 00:00:00 2001 From: milanmajchrak Date: Thu, 3 Oct 2024 12:58:25 +0200 Subject: [PATCH 2/6] Shibboleth login - sort the emails passed in the shibboleth email header and get the first one. --- .../clarin/ClarinShibAuthentication.java | 24 +++++++++---------- .../ClarinShibbolethLoginFilterIT.java | 24 ++++++++++++++++++- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java b/dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java index 5fe2a34c2d33..aeb194e4f2ce 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java @@ -20,6 +20,7 @@ import java.util.Objects; import java.util.UUID; import java.util.regex.Pattern; +import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -1208,20 +1209,17 @@ public String findSingleAttribute(HttpServletRequest request, String name) { if (value != null) { // If there are multiple values encoded in the shibboleth attribute // they are separated by a semicolon, and any semicolons in the - // attribute are escaped with a backslash. For this case we are just - // looking for the first attribute so we scan the value until we find - // the first unescaped semicolon and chop off everything else. - int idx = 0; - do { - idx = value.indexOf(';', idx); - if (idx != -1 && value.charAt(idx - 1) != '\\') { - value = value.substring(0, idx); - break; - } - } while (idx >= 0); + // attribute are escaped with a backslash. + // Step 1: Split the input string into email addresses + List emails = Arrays.stream(value.split("(? email.replaceAll("\\\\;", ";")) // Unescape semicolons + .collect(Collectors.toList()); + + // Step 2: Sort the email list alphabetically + emails.sort(String::compareToIgnoreCase); - // Unescape the semicolon after splitting - value = value.replaceAll("\\;", ";"); + // Step 3: Get the first sorted email + value = emails.get(0); } return value; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ClarinShibbolethLoginFilterIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ClarinShibbolethLoginFilterIT.java index 6f601065b3c6..78329a98563d 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ClarinShibbolethLoginFilterIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ClarinShibbolethLoginFilterIT.java @@ -527,10 +527,32 @@ public void testSuccessFullLoginPersistentIdNetId() throws Exception { deleteShibbolethUser(ePerson); } + @Test + public void testSuccessFullLoginWithTwoEmails() throws Exception { + String firstEmail = "efg@test.edu"; + String secondEmail = "abc@test.edu"; + String token = getClient().perform(get("/api/authn/shibboleth") + .header("Shib-Identity-Provider", IDP_TEST_EPERSON) + .header("SHIB-MAIL", firstEmail + ";" + secondEmail)) + .andExpect(status().is3xxRedirection()) + .andExpect(redirectedUrl("http://localhost:4000")) + .andReturn().getResponse().getHeader("Authorization"); + + checkUserIsSignedIn(token); + // Find the user by the second email + EPerson ePerson = checkUserWasCreated(null, IDP_TEST_EPERSON, secondEmail, null); + deleteShibbolethUser(ePerson); + } + private EPerson checkUserWasCreated(String netIdValue, String idpValue, String email, String name) throws SQLException { // Check if was created a user with such email and netid. - EPerson ePerson = ePersonService.findByNetid(context, Util.formatNetId(netIdValue, idpValue)); + EPerson ePerson = null; + if (netIdValue != null) { + ePerson = ePersonService.findByNetid(context, Util.formatNetId(netIdValue, idpValue)); + } else { + ePerson = ePersonService.findByEmail(context, email); + } assertTrue(Objects.nonNull(ePerson)); if (email != null) { assertEquals(ePerson.getEmail(), email); From e2732a7abb52d081489c7f60f2b40639b16609f4 Mon Sep 17 00:00:00 2001 From: milanmajchrak Date: Thu, 3 Oct 2024 14:29:05 +0200 Subject: [PATCH 3/6] The user is redirected to the login page when it is trying to update eperson email which is already assigned to another eperson. --- .../clarin/ClarinShibAuthentication.java | 11 ++++++- .../ClarinShibbolethLoginFilterIT.java | 32 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java b/dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java index aeb194e4f2ce..a83ccc8e6804 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java @@ -853,7 +853,16 @@ protected void updateEPerson(Context context, HttpServletRequest request, EPerso } // The email could have changed if using netid based lookup. if (email != null) { - eperson.setEmail(email.toLowerCase()); + String lowerCaseEmail = email.toLowerCase(); + // Check the email is unique + EPerson epersonByEmail = ePersonService.findByEmail(context, lowerCaseEmail); + if (epersonByEmail != null && !epersonByEmail.getID().equals(eperson.getID())) { + log.error("Unable to update the eperson's email metadata because the email '{}' is already in use.", + lowerCaseEmail); + throw new AuthorizeException("The email address is already in use."); + } else { + eperson.setEmail(email.toLowerCase()); + } } if (fname != null) { eperson.setFirstName(context, fname); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ClarinShibbolethLoginFilterIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ClarinShibbolethLoginFilterIT.java index 78329a98563d..ea1d6941faef 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ClarinShibbolethLoginFilterIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ClarinShibbolethLoginFilterIT.java @@ -544,6 +544,38 @@ public void testSuccessFullLoginWithTwoEmails() throws Exception { deleteShibbolethUser(ePerson); } + // The user has changed the email. But that email is already used by another user. + @Test + public void testDuplicateEmailError() throws Exception { + String userWithEppnEmail = "user@eppn.sk"; + String customEppn = "custom eppn"; + + // Create a user with netid and email + String tokenEppnUser = getClient().perform(get("/api/authn/shibboleth") + .header("Shib-Identity-Provider", IDP_TEST_EPERSON) + .header(NET_ID_PERSISTENT_ID, customEppn) + .header("SHIB-MAIL", userWithEppnEmail)) + .andExpect(status().is3xxRedirection()) + .andExpect(redirectedUrl("http://localhost:4000")) + .andReturn().getResponse().getHeader("Authorization"); + + checkUserIsSignedIn(tokenEppnUser); + + // Try to update an email of existing user - the email is already used by another user - the user should be + // redirected to the login page + getClient().perform(get("/api/authn/shibboleth") + .header("Shib-Identity-Provider", IDP_TEST_EPERSON) + .header(NET_ID_PERSISTENT_ID, NET_ID_TEST_EPERSON) + .header("SHIB-MAIL", userWithEppnEmail)) + .andExpect(status().is3xxRedirection()) + .andExpect(redirectedUrl("http://localhost:4000/login/")); + + // Check if was created a user with such email and netid. + EPerson ePerson = checkUserWasCreated(customEppn, IDP_TEST_EPERSON, userWithEppnEmail, null); + // Delete created eperson - clean after the test + deleteShibbolethUser(ePerson); + } + private EPerson checkUserWasCreated(String netIdValue, String idpValue, String email, String name) throws SQLException { // Check if was created a user with such email and netid. From dee964e33638a8acc54b994d162310c2c47a5105 Mon Sep 17 00:00:00 2001 From: milanmajchrak Date: Thu, 3 Oct 2024 18:42:13 +0200 Subject: [PATCH 4/6] Sorting emails is moved into specific method and ShibbolethLoginFilter is updated following the ShibAuthentication changes --- .../clarin/ClarinShibAuthentication.java | 34 ++++++++++++------- .../authenticate/clarin/ShibHeaders.java | 4 +++ .../clarin/ClarinShibbolethLoginFilter.java | 34 ++++++++++++------- .../ClarinShibbolethLoginFilterIT.java | 28 ++++++++++++++- 4 files changed, 73 insertions(+), 27 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java b/dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java index a83ccc8e6804..f7095904359b 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java @@ -1216,24 +1216,32 @@ public String findSingleAttribute(HttpServletRequest request, String name) { if (value != null) { - // If there are multiple values encoded in the shibboleth attribute - // they are separated by a semicolon, and any semicolons in the - // attribute are escaped with a backslash. - // Step 1: Split the input string into email addresses - List emails = Arrays.stream(value.split("(? email.replaceAll("\\\\;", ";")) // Unescape semicolons - .collect(Collectors.toList()); - - // Step 2: Sort the email list alphabetically - emails.sort(String::compareToIgnoreCase); - - // Step 3: Get the first sorted email - value = emails.get(0); + sortEmailsAndGetFirst(value); } return value; } + /** + * Sort the email addresses and return the first one. + * @param value The email addresses separated by semicolons. + */ + public static String sortEmailsAndGetFirst(String value) { + // If there are multiple values encoded in the shibboleth attribute + // they are separated by a semicolon, and any semicolons in the + // attribute are escaped with a backslash. + // Step 1: Split the input string into email addresses + List emails = Arrays.stream(value.split("(? email.replaceAll("\\\\;", ";")) // Unescape semicolons + .collect(Collectors.toList()); + + // Step 2: Sort the email list alphabetically + emails.sort(String::compareToIgnoreCase); + + // Step 3: Get the first sorted email + return emails.get(0); + } + /** * Find a particular Shibboleth hattributeeader value and return the values. * The attribute name uses a bit of fuzzy logic, so it will first try case diff --git a/dspace-api/src/main/java/org/dspace/authenticate/clarin/ShibHeaders.java b/dspace-api/src/main/java/org/dspace/authenticate/clarin/ShibHeaders.java index 84ae41b4fa6c..7b0acb3dd875 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/clarin/ShibHeaders.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/clarin/ShibHeaders.java @@ -153,4 +153,8 @@ public void log_headers() { private void initializeNetIdHeader() { this.netIdHeaders = configurationService.getArrayProperty("authentication-shibboleth.netid-header"); } + + public List getNetIdHeaders() { + return Arrays.asList(this.netIdHeaders); + } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/clarin/ClarinShibbolethLoginFilter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/clarin/ClarinShibbolethLoginFilter.java index 78887d5f5e58..d938dddb4f0b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/clarin/ClarinShibbolethLoginFilter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/clarin/ClarinShibbolethLoginFilter.java @@ -126,7 +126,6 @@ public Authentication attemptAuthentication(HttpServletRequest req, // If the Idp doesn't send the email in the request header, send the redirect order to the FE for the user // to fill in the email. - String netidHeader = configurationService.getProperty("authentication-shibboleth.netid-header"); String emailHeader = configurationService.getProperty("authentication-shibboleth.email-header"); Context context = ContextUtil.obtainContext(req); @@ -154,33 +153,42 @@ public Authentication attemptAuthentication(HttpServletRequest req, shib_headers = new ShibHeaders(req); } - // Retrieve the netid and email values from the header. - String netid = shib_headers.get_single(netidHeader); String idp = shib_headers.get_idp(); // If the clarin verification object is not null load the email from there otherwise from header. - String email = Objects.isNull(clarinVerificationToken) ? - shib_headers.get_single(emailHeader) : clarinVerificationToken.getEmail(); + String email; + if (Objects.isNull(clarinVerificationToken)) { + email = shib_headers.get_single(emailHeader); + if (StringUtils.isNotEmpty(email)) { + email = ClarinShibAuthentication.sortEmailsAndGetFirst(email); + } + } else { + email = clarinVerificationToken.getEmail(); + } EPerson ePerson = null; - if (StringUtils.isNotEmpty(netid)) { + // 1. Try find the user by the netid + // Retrieve the netid and email values from the header. + for (String netidHeader : shib_headers.getNetIdHeaders()) { try { + netidHeader = netidHeader.trim(); + String netid = shib_headers.get_single(netidHeader); // If email is null and netid exist try to find the eperson by netid and load its email if (StringUtils.isEmpty(email)) { ePerson = ePersonService.findByNetid(context, netid); email = Objects.isNull(email) ? this.getEpersonEmail(ePerson) : null; - } else { - // Try to get user by the email because of possible duplicate of the user email - ePerson = ePersonService.findByEmail(context, email); } } catch (SQLException ignored) { // } } - // logging - log.info("Shib-Identity-Provider: " + idp); - log.info("authentication-shibboleth.netid-header: " + netidHeader + " with value: " + netid); - log.info("authentication-shibboleth.email-header: " + emailHeader + " with value: " + email); + if (Objects.isNull(ePerson) && StringUtils.isNotEmpty(email)) { + try { + ePerson = ePersonService.findByEmail(context, email); + } catch (SQLException e) { + // + } + } try { if (StringUtils.isEmpty(idp)) { diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ClarinShibbolethLoginFilterIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ClarinShibbolethLoginFilterIT.java index ea1d6941faef..92200faa8c2c 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ClarinShibbolethLoginFilterIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ClarinShibbolethLoginFilterIT.java @@ -229,7 +229,6 @@ public void testShouldReturnDuplicateUserError() throws Exception { .andExpect(redirectedUrl("http://localhost:4000")) .andReturn().getResponse().getHeader("Authorization"); - checkUserIsSignedIn(token); // Check if was created a user with such email and netid. @@ -252,6 +251,33 @@ public void testShouldReturnDuplicateUserError() throws Exception { EPersonBuilder.deleteEPerson(ePerson.getID()); } + // Login with email without netid, but the user with such email already exists and it has assigned netid. + @Test + public void testShouldReturnDuplicateUserErrorLoginWithoutNetId() throws Exception { + String email = "test@mail.epic"; + String netId = email; + + // login through shibboleth + String token = getClient().perform(get("/api/authn/shibboleth") + .header("SHIB-MAIL", email) + .header("SHIB-NETID", netId) + .header("Shib-Identity-Provider", IDP_TEST_EPERSON)) + .andExpect(status().is3xxRedirection()) + .andExpect(redirectedUrl("http://localhost:4000")) + .andReturn().getResponse().getHeader("Authorization"); + + checkUserIsSignedIn(token); + + // login through shibboleth + String tokenDuplicate = getClient().perform(get("/api/authn/shibboleth") + .header("SHIB-MAIL", email) + .header("Shib-Identity-Provider", IDP_TEST_EPERSON)) + .andExpect(status().is3xxRedirection()) + .andExpect(redirectedUrl("http://localhost:4000/login/duplicate-user?email=" + email)) + .andReturn().getResponse().getHeader("Authorization"); + + } + // This test is copied from the `ShibbolethLoginFilterIT` and modified following the Clarin updates. @Test public void testRedirectToGivenTrustedUrl() throws Exception { From 574dcac0814da6e705b86fd6d80389ad6d255f36 Mon Sep 17 00:00:00 2001 From: milanmajchrak Date: Thu, 3 Oct 2024 19:49:51 +0200 Subject: [PATCH 5/6] Fixed failing tests --- .../authenticate/clarin/ClarinShibAuthentication.java | 5 +---- .../app/rest/security/ClarinShibbolethLoginFilterIT.java | 8 ++++---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java b/dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java index f7095904359b..41f968ff02ec 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java @@ -1211,14 +1211,11 @@ public String findSingleAttribute(HttpServletRequest request, String name) { if (name == null) { return null; } - String value = findAttribute(request, name); - if (value != null) { - sortEmailsAndGetFirst(value); + value = sortEmailsAndGetFirst(value); } - return value; } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ClarinShibbolethLoginFilterIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ClarinShibbolethLoginFilterIT.java index 92200faa8c2c..343f0c5fe035 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ClarinShibbolethLoginFilterIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ClarinShibbolethLoginFilterIT.java @@ -254,7 +254,7 @@ public void testShouldReturnDuplicateUserError() throws Exception { // Login with email without netid, but the user with such email already exists and it has assigned netid. @Test public void testShouldReturnDuplicateUserErrorLoginWithoutNetId() throws Exception { - String email = "test@mail.epic"; + String email = "test@email.sk"; String netId = email; // login through shibboleth @@ -268,8 +268,8 @@ public void testShouldReturnDuplicateUserErrorLoginWithoutNetId() throws Excepti checkUserIsSignedIn(token); - // login through shibboleth - String tokenDuplicate = getClient().perform(get("/api/authn/shibboleth") + // Should not login because the user with such email already exists + getClient().perform(get("/api/authn/shibboleth") .header("SHIB-MAIL", email) .header("Shib-Identity-Provider", IDP_TEST_EPERSON)) .andExpect(status().is3xxRedirection()) @@ -594,7 +594,7 @@ public void testDuplicateEmailError() throws Exception { .header(NET_ID_PERSISTENT_ID, NET_ID_TEST_EPERSON) .header("SHIB-MAIL", userWithEppnEmail)) .andExpect(status().is3xxRedirection()) - .andExpect(redirectedUrl("http://localhost:4000/login/")); + .andExpect(redirectedUrl("http://localhost:4000/login/duplicate-user?email=" + userWithEppnEmail)); // Check if was created a user with such email and netid. EPerson ePerson = checkUserWasCreated(customEppn, IDP_TEST_EPERSON, userWithEppnEmail, null); From a01d9bd7cef0d473bc9bb142f88d186c1094e02b Mon Sep 17 00:00:00 2001 From: milanmajchrak Date: Thu, 3 Oct 2024 20:08:56 +0200 Subject: [PATCH 6/6] The ClarinShibbolethLoginFilter and ClarinShibAuthentication has duplicate code, I put it into static method. --- .../clarin/ClarinShibAuthentication.java | 90 ++++++++++--------- .../authenticate/clarin/ShibHeaders.java | 4 +- .../clarin/ClarinShibbolethLoginFilter.java | 21 ++--- 3 files changed, 58 insertions(+), 57 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java b/dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java index 41f968ff02ec..98c030be80c7 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java @@ -557,26 +557,9 @@ protected EPerson findEPerson(Context context, HttpServletRequest request, Strin // 1) First, look for a netid header. if (netidHeaders != null) { - // Go through all the netid headers and try to find a user. It could be e.g., `eppn`, `persistent-id`,.. - for (String netidHeader : netidHeaders) { - netidHeader = netidHeader.trim(); - String netid = shibheaders.get_single(netidHeader); - if (netid == null) { - continue; - } - + eperson = findEpersonByNetId(netidHeaders, shibheaders, eperson, ePersonService, context, true); + if (eperson != null) { foundNetID = true; - eperson = ePersonService.findByNetid(context, netid); - - if (eperson == null) { - log.info( - "Unable to identify EPerson based upon Shibboleth netid header: '" + netidHeader + - "'='" + netid + "'."); - } else { - log.debug( - "Identified EPerson based upon Shibboleth netid header: '" + netidHeader + "'='" + - netid + "'" + "."); - } } } @@ -659,7 +642,6 @@ protected EPerson findEPerson(Context context, HttpServletRequest request, Strin return eperson; } - /** * Register a new eperson object. This method is called when no existing user was * found for the NetID or Email and autoregister is enabled. When these conditions @@ -1219,26 +1201,6 @@ public String findSingleAttribute(HttpServletRequest request, String name) { return value; } - /** - * Sort the email addresses and return the first one. - * @param value The email addresses separated by semicolons. - */ - public static String sortEmailsAndGetFirst(String value) { - // If there are multiple values encoded in the shibboleth attribute - // they are separated by a semicolon, and any semicolons in the - // attribute are escaped with a backslash. - // Step 1: Split the input string into email addresses - List emails = Arrays.stream(value.split("(? email.replaceAll("\\\\;", ";")) // Unescape semicolons - .collect(Collectors.toList()); - - // Step 2: Sort the email list alphabetically - emails.sort(String::compareToIgnoreCase); - - // Step 3: Get the first sorted email - return emails.get(0); - } - /** * Find a particular Shibboleth hattributeeader value and return the values. * The attribute name uses a bit of fuzzy logic, so it will first try case @@ -1345,6 +1307,54 @@ public String getEmailAcceptedOrNull(String email) { return email; } + /** + * Find an EPerson by a NetID header. The method will go through all the netid headers and try to find a user. + */ + public static EPerson findEpersonByNetId(String[] netidHeaders, ShibHeaders shibheaders, EPerson eperson, + EPersonService ePersonService, Context context, boolean logAllowed) + throws SQLException { + // Go through all the netid headers and try to find a user. It could be e.g., `eppn`, `persistent-id`,.. + for (String netidHeader : netidHeaders) { + netidHeader = netidHeader.trim(); + String netid = shibheaders.get_single(netidHeader); + if (netid == null) { + continue; + } + + eperson = ePersonService.findByNetid(context, netid); + + if (eperson == null && logAllowed) { + log.info( + "Unable to identify EPerson based upon Shibboleth netid header: '" + netidHeader + + "'='" + netid + "'."); + } else { + log.debug( + "Identified EPerson based upon Shibboleth netid header: '" + netidHeader + "'='" + + netid + "'" + "."); + } + } + return eperson; + } + + /** + * Sort the email addresses and return the first one. + * @param value The email addresses separated by semicolons. + */ + public static String sortEmailsAndGetFirst(String value) { + // If there are multiple values encoded in the shibboleth attribute + // they are separated by a semicolon, and any semicolons in the + // attribute are escaped with a backslash. + // Step 1: Split the input string into email addresses + List emails = Arrays.stream(value.split("(? email.replaceAll("\\\\;", ";")) // Unescape semicolons + .collect(Collectors.toList()); + + // Step 2: Sort the email list alphabetically + emails.sort(String::compareToIgnoreCase); + + // Step 3: Get the first sorted email + return emails.get(0); + } /** * Get the first netid from the list of netid headers. E.g., eppn, persistent-id,... diff --git a/dspace-api/src/main/java/org/dspace/authenticate/clarin/ShibHeaders.java b/dspace-api/src/main/java/org/dspace/authenticate/clarin/ShibHeaders.java index 7b0acb3dd875..a4b85e53be2e 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/clarin/ShibHeaders.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/clarin/ShibHeaders.java @@ -154,7 +154,7 @@ private void initializeNetIdHeader() { this.netIdHeaders = configurationService.getArrayProperty("authentication-shibboleth.netid-header"); } - public List getNetIdHeaders() { - return Arrays.asList(this.netIdHeaders); + public String[] getNetIdHeaders() { + return this.netIdHeaders; } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/clarin/ClarinShibbolethLoginFilter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/clarin/ClarinShibbolethLoginFilter.java index d938dddb4f0b..821be38ed2a2 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/clarin/ClarinShibbolethLoginFilter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/clarin/ClarinShibbolethLoginFilter.java @@ -166,27 +166,18 @@ public Authentication attemptAuthentication(HttpServletRequest req, } EPerson ePerson = null; - // 1. Try find the user by the netid - // Retrieve the netid and email values from the header. - for (String netidHeader : shib_headers.getNetIdHeaders()) { - try { - netidHeader = netidHeader.trim(); - String netid = shib_headers.get_single(netidHeader); - // If email is null and netid exist try to find the eperson by netid and load its email - if (StringUtils.isEmpty(email)) { - ePerson = ePersonService.findByNetid(context, netid); - email = Objects.isNull(email) ? this.getEpersonEmail(ePerson) : null; - } - } catch (SQLException ignored) { - // - } + try { + ePerson = ClarinShibAuthentication.findEpersonByNetId(shib_headers.getNetIdHeaders(), shib_headers, ePerson, + ePersonService, context, false); + } catch (SQLException e) { + // It is logged in the ClarinShibAuthentication class. } if (Objects.isNull(ePerson) && StringUtils.isNotEmpty(email)) { try { ePerson = ePersonService.findByEmail(context, email); } catch (SQLException e) { - // + // It is logged in the ClarinShibAuthentication class. } }