[DS-3819] Revert back to 401 status and move login URL to WWW-Authenticate header

This commit is contained in:
Tom Desair
2018-03-01 10:41:28 +01:00
parent 93549cab24
commit 55f5571e1d
9 changed files with 48 additions and 15 deletions

View File

@@ -210,4 +210,10 @@ public interface AuthenticationMethod {
public String loginPageURL(Context context,
HttpServletRequest request,
HttpServletResponse response);
/**
* Returns a short name that uniquely identifies this authentication method
* @return The authentication method name
*/
public String getName();
}

View File

@@ -276,4 +276,9 @@ public class IPAuthentication implements AuthenticationMethod {
HttpServletResponse response) {
return null;
}
@Override
public String getName() {
return "ip";
}
}

View File

@@ -639,6 +639,11 @@ public class LDAPAuthentication
return null;
}
@Override
public String getName() {
return "ldap";
}
/*
* Add authenticated users to the group defined in dspace.cfg by
* the authentication-ldap.login.groupmap.* key.

View File

@@ -242,4 +242,9 @@ public class PasswordAuthentication
HttpServletResponse response) {
return null;
}
@Override
public String getName() {
return "password";
}
}

View File

@@ -538,6 +538,11 @@ public class ShibAuthentication implements AuthenticationMethod {
}
}
@Override
public String getName() {
return "shibboleth";
}
/**
* Identify an existing EPerson based upon the shibboleth attributes provided on
* the request object. There are three cases where this can occurr, each as

View File

@@ -589,4 +589,9 @@ public class X509Authentication implements AuthenticationMethod {
HttpServletResponse response) {
return loginPageURL;
}
@Override
public String getName() {
return "x509";
}
}

View File

@@ -82,26 +82,26 @@ public class StatelessLoginFilter extends AbstractAuthenticationProcessingFilter
Iterator<AuthenticationMethod> authenticationMethodIterator
= authenticationService.authenticationMethodIterator();
Context context = ContextUtil.obtainContext(request);
String redirectUrl = null;
StringBuilder wwwAuthenticate = new StringBuilder();
while (authenticationMethodIterator.hasNext()) {
AuthenticationMethod authenticationMethod = authenticationMethodIterator.next();
if (wwwAuthenticate.length() > 0) {
wwwAuthenticate.append(", ");
}
wwwAuthenticate.append(authenticationMethod.getName()).append(" realm=\"DSpace REST API\"");
String loginPageURL = authenticationMethod.loginPageURL(context, request, response);
if (StringUtils.isNotBlank(loginPageURL)) {
redirectUrl = loginPageURL;
// We cannot reply with a 303 code because may browsers handle 3xx response codes transparently. This
// means that the JavaScript client code is not aware of the 303 status and fails to react accordingly.
wwwAuthenticate.append(", location=\"").append(loginPageURL).append("\"");
}
}
String wwwAuthenticate = "Bearer realm=\"DSpace REST API\"";
if (redirectUrl != null) {
//We cannot reply with a 303 code because may browsers handle 3xx response codes transparently.
//This means that the JavaScript client code is not aware of the 303 status and fails to react accordingly.
wwwAuthenticate = wwwAuthenticate + ", location=\"" + redirectUrl + "\"";
}
response.setHeader("WWW-Authenticate", wwwAuthenticate);
response.setHeader("WWW-Authenticate", wwwAuthenticate.toString());
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, failed.getMessage());
}
}

View File

@@ -91,7 +91,7 @@
type : 'POST',
success : successHandler,
error : function(result, status, xhr) {
if (xhr == 401) {
if (result.status === 401) {
var authenticate = result.getResponseHeader("WWW-Authenticate");
if(authenticate !== null) {
var loc = /location="([^,]*)"/.exec(authenticate);

View File

@@ -344,6 +344,7 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
@Test
public void testShibbolethLoginRequestAttribute() throws Exception {
context.turnOffAuthorisationSystem();
//Enable Shibboleth login
configurationService.setProperty("plugin.sequence.org.dspace.authenticate.AuthenticationMethod", SHIB_ONLY);
@@ -354,18 +355,19 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
//Faculty members are assigned to the Reviewers group
configurationService.setProperty("authentication-shibboleth.role.faculty", "Reviewers");
context.restoreAuthSystemState();
getClient().perform(get("/api/authn/login").header("Referer", "http://my.uni.edu"))
.andExpect(status().isUnauthorized())
.andExpect(header().string("WWW-Authenticate",
"Bearer realm=\"DSpace REST API\", " +
"shibboleth realm=\"DSpace REST API\", " +
"location=\"/Shibboleth.sso/Login?target=http%3A%2F%2Fmy.uni.edu\""));
//Simulate that a shibboleth authentication has happened
String token = getClient().perform(post("/api/authn/login")
.requestAttr("SHIB-MAIL", eperson.getEmail())
.requestAttr("SHIB-SCOPED-AFFILIATION", "faculty,staff"))
.requestAttr("SHIB-SCOPED-AFFILIATION", "faculty;staff"))
.andExpect(status().isOk())
.andReturn().getResponse().getHeader(AUTHORIZATION_HEADER);
@@ -393,7 +395,7 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
.with(ip("123.123.123.123")))
.andExpect(status().isUnauthorized())
.andExpect(header().string("WWW-Authenticate",
"Bearer realm=\"DSpace REST API\", " +
"ip realm=\"DSpace REST API\", shibboleth realm=\"DSpace REST API\", " +
"location=\"/Shibboleth.sso/Login?target=http%3A%2F%2Fmy.uni.edu\""));
//Simulate that a shibboleth authentication has happened