Skip to content

Commit

Permalink
UFAL/Shibboleth - show error in the UI when shibboleth authentication…
Browse files Browse the repository at this point in the history
… is failed (#810)

* The user is not signed in without using link with the verification token from the email/

* Send a redirect to UI with specific parameter that the Shibboleth authorization wasn't successful
  • Loading branch information
milanmajchrak authored Nov 14, 2024
1 parent 9f8d2c5 commit 2e92ed8
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 0 deletions.
17 changes: 17 additions & 0 deletions dspace-api/src/main/java/org/dspace/core/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -506,4 +506,21 @@ public static String interpolateConfigsInString(String string) {
ConfigurationService config = DSpaceServicesFactory.getInstance().getConfigurationService();
return StringSubstitutor.replace(string, config.getProperties());
}

/**
* Replace the last occurrence of a substring within a string.
*
* @param input The input string
* @param toReplace The substring to replace
* @param replacement The replacement substring
* @return Replaced input string or the original input string if the substring to replace is not found
*/
public static String replaceLast(String input, String toReplace, String replacement) {
int lastIndex = input.lastIndexOf(toReplace);
if (lastIndex == -1) {
return input; // No replacement if not found
}

return input.substring(0, lastIndex) + replacement + input.substring(lastIndex + toReplace.length());
}
}
20 changes: 20 additions & 0 deletions dspace-api/src/test/java/org/dspace/core/UtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,24 @@ public void testInterpolateConfigsInString() {
// remove the config we added
configurationService.setProperty(configName, null);
}

// Replace the last occurrence of a substring
@Test
public void testReplaceLast_SingleOccurrence() {
String input = "/login/";
String result = Utils.replaceLast(input, "/", "replacement");

// Expected output: "/loginreplacement"
assertEquals("/loginreplacement", result);
}

// No replacement when the substring is not found
@Test
public void testReplaceLast_NoMatch() {
String input = "/login";
String result = Utils.replaceLast(input, "/", "replacement");

// Expected output: "/login"
assertEquals("replacementlogin", result);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ protected void unsuccessfulAuthentication(HttpServletRequest request,
String missingHeadersUrl = "missing-headers";
String userWithoutEmailUrl = "auth-failed";
String duplicateUser = "duplicate-user";
String cannotAuthenticate = "shibboleth-authentication-failed";

// Compose the redirect URL
if (this.isMissingHeadersFromIdp) {
Expand All @@ -270,6 +271,11 @@ protected void unsuccessfulAuthentication(HttpServletRequest request,
} else if (StringUtils.isNotEmpty(this.netId)) {
// netId is set if the user doesn't have the email
redirectUrl += userWithoutEmailUrl + "?netid=" + this.netId;
} else {
// Remove the last slash from the URL `login/`
String redirectUrlWithoutSlash = redirectUrl.endsWith("/") ?
Utils.replaceLast(redirectUrl, "/", "") : redirectUrl;
redirectUrl = redirectUrlWithoutSlash + "?error=" + cannotAuthenticate;
}

response.sendRedirect(redirectUrl);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,18 @@ public void shouldNotAuthenticateOnSecondAttemptWithoutVerificationTokenInReques
Util.formatNetId(netId, idp)));
}

@Test
public void shouldSendShibbolethAuthError() throws Exception {
String idp = "Test Idp";

// Try to authenticate but the Shibboleth doesn't send the email or netid in the header,
// so the user won't be registered but the user will be redirected to the login page with the error message.
getClient().perform(get("/api/authn/shibboleth")
.header("Shib-Identity-Provider", idp))
.andExpect(status().isFound())
.andExpect(redirectedUrl("http://localhost:4000/login?error=shibboleth-authentication-failed"));
}

private EPerson checkUserWasCreated(String netIdValue, String idpValue, String email, String name)
throws SQLException {
// Check if was created a user with such email and netid.
Expand Down

0 comments on commit 2e92ed8

Please sign in to comment.