mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-14 05:23:14 +00:00
[CST-5669] Improved OrcidLoginFilter
This commit is contained in:
@@ -8,10 +8,12 @@
|
||||
package org.dspace.authenticate;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.dspace.authenticate.factory.AuthenticateServiceFactory;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.eperson.Group;
|
||||
@@ -29,6 +31,26 @@ public class OrcidAuthentication implements AuthenticationMethod {
|
||||
|
||||
private final ServiceManager serviceManager = new DSpace().getServiceManager();
|
||||
|
||||
/**
|
||||
* Check if OrcidAuthentication plugin is enabled
|
||||
* @return true if enabled, false otherwise
|
||||
*/
|
||||
public static boolean isEnabled() {
|
||||
|
||||
String pluginName = new OrcidAuthentication().getName();
|
||||
|
||||
Iterator<AuthenticationMethod> authenticationMethodIterator = AuthenticateServiceFactory.getInstance()
|
||||
.getAuthenticationService().authenticationMethodIterator();
|
||||
|
||||
while (authenticationMethodIterator.hasNext()) {
|
||||
if (pluginName.equals(authenticationMethodIterator.next().getName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSelfRegister(Context context, HttpServletRequest request, String username) throws SQLException {
|
||||
return getOrcidAuthentication().canSelfRegister(context, request, username);
|
||||
|
@@ -87,7 +87,7 @@ public class OrcidAuthenticationBean implements AuthenticationMethod {
|
||||
LOGGER.warn("The incoming request has not code parameter");
|
||||
return NO_SUCH_USER;
|
||||
}
|
||||
|
||||
request.setAttribute(ORCID_AUTH_ATTRIBUTE, true);
|
||||
return authenticateWithOrcid(context, code, request);
|
||||
}
|
||||
|
||||
|
@@ -1,58 +0,0 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dspace.app.rest.model.AuthnRest;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Rest controller that handles redirect after ORCID authentication succeded.
|
||||
*
|
||||
* @author Luca Giamminonni (luca.giamminonni at 4science.it)
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(value = "/api/" + AuthnRest.CATEGORY + "/orcid")
|
||||
public class OrcidAuthenticationRestController {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(OrcidAuthenticationRestController.class);
|
||||
|
||||
@Autowired
|
||||
private ConfigurationService configurationService;
|
||||
|
||||
@Autowired
|
||||
private DiscoverableEndpointsService discoverableEndpointsService;
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
discoverableEndpointsService.register(this, Arrays.asList(Link.of("/api/" + AuthnRest.CATEGORY, "orcid")));
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public void orcid(HttpServletResponse response,
|
||||
@RequestParam(name = "redirectUrl", required = false) String redirectUrl) throws IOException {
|
||||
if (StringUtils.isBlank(redirectUrl)) {
|
||||
redirectUrl = configurationService.getProperty("dspace.ui.url");
|
||||
}
|
||||
log.info("Redirecting to " + redirectUrl);
|
||||
response.sendRedirect(redirectUrl);
|
||||
}
|
||||
}
|
@@ -1,53 +0,0 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.security;
|
||||
|
||||
import static org.dspace.authenticate.OrcidAuthenticationBean.ORCID_AUTH_ATTRIBUTE;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
|
||||
/**
|
||||
* This class will filter ORCID requests and try and authenticate them.
|
||||
*
|
||||
* @author Luca Giamminonni (luca.giamminonni at 4science.it)
|
||||
*/
|
||||
|
||||
public class OrcidAuthenticationFilter extends StatelessLoginFilter {
|
||||
|
||||
public OrcidAuthenticationFilter(String url, AuthenticationManager authenticationManager,
|
||||
RestAuthenticationService restAuthenticationService) {
|
||||
super(url, authenticationManager, restAuthenticationService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
|
||||
throws AuthenticationException {
|
||||
|
||||
req.setAttribute(ORCID_AUTH_ATTRIBUTE, ORCID_AUTH_ATTRIBUTE);
|
||||
return authenticationManager.authenticate(new DSpaceAuthentication());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain,
|
||||
Authentication auth) throws IOException, ServletException {
|
||||
|
||||
restAuthenticationService.addAuthenticationDataForUser(req, res, (DSpaceAuthentication) auth, true);
|
||||
chain.doFilter(req, res);
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.security;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.authenticate.OrcidAuthentication;
|
||||
import org.dspace.core.Utils;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.ProviderNotFoundException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
|
||||
/**
|
||||
* This class will filter ORCID requests and try and authenticate them.
|
||||
*
|
||||
* @author Luca Giamminonni (luca.giamminonni at 4science.it)
|
||||
*/
|
||||
|
||||
public class OrcidLoginFilter extends StatelessLoginFilter {
|
||||
|
||||
private static final Logger log = LogManager.getLogger(OrcidLoginFilter.class);
|
||||
|
||||
private ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||
|
||||
public OrcidLoginFilter(String url, AuthenticationManager authenticationManager,
|
||||
RestAuthenticationService restAuthenticationService) {
|
||||
super(url, authenticationManager, restAuthenticationService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
|
||||
throws AuthenticationException {
|
||||
|
||||
if (!OrcidAuthentication.isEnabled()) {
|
||||
throw new ProviderNotFoundException("Orcid login is disabled.");
|
||||
}
|
||||
|
||||
return authenticationManager.authenticate(new DSpaceAuthentication());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain,
|
||||
Authentication auth) throws IOException, ServletException {
|
||||
|
||||
|
||||
DSpaceAuthentication dSpaceAuthentication = (DSpaceAuthentication) auth;
|
||||
|
||||
log.debug("Orcid authentication successful for EPerson {}. Sending back temporary auth cookie",
|
||||
dSpaceAuthentication.getName());
|
||||
|
||||
restAuthenticationService.addAuthenticationDataForUser(req, res, dSpaceAuthentication, true);
|
||||
|
||||
redirectAfterSuccess(req, res);
|
||||
}
|
||||
|
||||
/**
|
||||
* After successful login, redirect to the DSpace URL specified by this Orcid
|
||||
* request (in the "redirectUrl" request parameter). If that 'redirectUrl' is
|
||||
* not valid or trusted for this DSpace site, then return a 400 error.
|
||||
* @param request
|
||||
* @param response
|
||||
* @throws IOException
|
||||
*/
|
||||
private void redirectAfterSuccess(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
// Get redirect URL from request parameter
|
||||
String redirectUrl = request.getParameter("redirectUrl");
|
||||
|
||||
// If redirectUrl unspecified, default to the configured UI
|
||||
if (StringUtils.isEmpty(redirectUrl)) {
|
||||
redirectUrl = configurationService.getProperty("dspace.ui.url");
|
||||
}
|
||||
|
||||
// Validate that the redirectURL matches either the server or UI hostname. It
|
||||
// *cannot* be an arbitrary URL.
|
||||
String redirectHostName = Utils.getHostName(redirectUrl);
|
||||
String serverHostName = Utils.getHostName(configurationService.getProperty("dspace.server.url"));
|
||||
ArrayList<String> allowedHostNames = new ArrayList<>();
|
||||
allowedHostNames.add(serverHostName);
|
||||
String[] allowedUrls = configurationService.getArrayProperty("rest.cors.allowed-origins");
|
||||
for (String url : allowedUrls) {
|
||||
allowedHostNames.add(Utils.getHostName(url));
|
||||
}
|
||||
|
||||
if (StringUtils.equalsAnyIgnoreCase(redirectHostName, allowedHostNames.toArray(new String[0]))) {
|
||||
log.debug("Orcid redirecting to " + redirectUrl);
|
||||
response.sendRedirect(redirectUrl);
|
||||
} else {
|
||||
log.error("Invalid Orcid redirectURL=" + redirectUrl +
|
||||
". URL doesn't match hostname of server or UI!");
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST,
|
||||
"Invalid redirectURL! Must match server or ui hostname.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -141,7 +141,7 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
LogoutFilter.class)
|
||||
//Add a filter before our ORCID endpoints to do the authentication based on the data in the
|
||||
// HTTP request
|
||||
.addFilterBefore(new OrcidAuthenticationFilter("/api/authn/orcid", authenticationManager(),
|
||||
.addFilterBefore(new OrcidLoginFilter("/api/authn/orcid", authenticationManager(),
|
||||
restAuthenticationService),
|
||||
LogoutFilter.class)
|
||||
//Add a filter before our OIDC endpoints to do the authentication based on the data in the
|
||||
|
@@ -19,6 +19,8 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
@@ -40,6 +42,9 @@ import com.nimbusds.jwt.JWTClaimsSet;
|
||||
import com.nimbusds.jwt.SignedJWT;
|
||||
import org.apache.commons.codec.CharEncoding;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.dspace.app.orcid.client.OrcidClient;
|
||||
import org.dspace.app.orcid.client.OrcidConfiguration;
|
||||
import org.dspace.app.orcid.model.OrcidTokenResponseDTO;
|
||||
import org.dspace.app.rest.authorization.Authorization;
|
||||
import org.dspace.app.rest.authorization.AuthorizationFeature;
|
||||
import org.dspace.app.rest.authorization.AuthorizationFeatureService;
|
||||
@@ -49,10 +54,12 @@ import org.dspace.app.rest.matcher.AuthenticationStatusMatcher;
|
||||
import org.dspace.app.rest.matcher.AuthorizationMatcher;
|
||||
import org.dspace.app.rest.matcher.EPersonMatcher;
|
||||
import org.dspace.app.rest.matcher.HalMatcher;
|
||||
import org.dspace.app.rest.model.AuthnRest;
|
||||
import org.dspace.app.rest.model.EPersonRest;
|
||||
import org.dspace.app.rest.projection.DefaultProjection;
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
import org.dspace.authenticate.OrcidAuthenticationBean;
|
||||
import org.dspace.builder.BitstreamBuilder;
|
||||
import org.dspace.builder.BundleBuilder;
|
||||
import org.dspace.builder.CollectionBuilder;
|
||||
@@ -93,11 +100,18 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
|
||||
@Autowired
|
||||
private AuthorizationFeatureService authorizationFeatureService;
|
||||
|
||||
@Autowired
|
||||
private OrcidConfiguration orcidConfiguration;
|
||||
|
||||
@Autowired
|
||||
private OrcidAuthenticationBean orcidAuthentication;
|
||||
|
||||
@Autowired
|
||||
private Utils utils;
|
||||
|
||||
public static final String[] PASS_ONLY = {"org.dspace.authenticate.PasswordAuthentication"};
|
||||
public static final String[] SHIB_ONLY = {"org.dspace.authenticate.ShibAuthentication"};
|
||||
public static final String[] ORCID_ONLY = { "org.dspace.authenticate.OrcidAuthentication" };
|
||||
public static final String[] SHIB_AND_PASS = {
|
||||
"org.dspace.authenticate.ShibAuthentication",
|
||||
"org.dspace.authenticate.PasswordAuthentication"
|
||||
@@ -1495,6 +1509,116 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
|
||||
.andExpect(status().isNoContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusOrcidAuthenticatedWithCookie() throws Exception {
|
||||
|
||||
configurationService.setProperty("plugin.sequence.org.dspace.authenticate.AuthenticationMethod", ORCID_ONLY);
|
||||
|
||||
String uiURL = configurationService.getProperty("dspace.ui.url");
|
||||
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
String orcid = "0000-1111-2222-3333";
|
||||
String code = "123456";
|
||||
String orcidAccessToken = "c41e37e5-c2de-4177-91d6-ed9e9d1f31bf";
|
||||
|
||||
EPersonBuilder.createEPerson(context)
|
||||
.withEmail("test@email.it")
|
||||
.withNetId(orcid)
|
||||
.withNameInMetadata("Test", "User")
|
||||
.withCanLogin(true)
|
||||
.build();
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
OrcidClient orcidClientMock = mock(OrcidClient.class);
|
||||
when(orcidClientMock.getAccessToken(code)).thenReturn(buildOrcidTokenResponse(orcid, orcidAccessToken));
|
||||
|
||||
OrcidClient originalOrcidClient = orcidAuthentication.getOrcidClient();
|
||||
orcidAuthentication.setOrcidClient(orcidClientMock);
|
||||
|
||||
Cookie authCookie = null;
|
||||
|
||||
try {
|
||||
|
||||
authCookie = getClient().perform(get("/api/" + AuthnRest.CATEGORY + "/orcid")
|
||||
.param("redirectUrl", uiURL)
|
||||
.param("code", code))
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl(uiURL))
|
||||
.andExpect(cookie().doesNotExist("DSPACE-XSRF-COOKIE"))
|
||||
.andExpect(header().doesNotExist("DSPACE-XSRF-TOKEN"))
|
||||
.andExpect(cookie().exists(AUTHORIZATION_COOKIE))
|
||||
.andReturn().getResponse().getCookie(AUTHORIZATION_COOKIE);
|
||||
|
||||
} finally {
|
||||
orcidAuthentication.setOrcidClient(originalOrcidClient);
|
||||
}
|
||||
|
||||
assertNotNull(authCookie);
|
||||
String token = authCookie.getValue();
|
||||
|
||||
getClient().perform(get("/api/authn/status").header("Origin", uiURL)
|
||||
.secure(true)
|
||||
.cookie(authCookie))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$.okay", is(true)))
|
||||
.andExpect(jsonPath("$.authenticated", is(true)))
|
||||
.andExpect(jsonPath("$.authenticationMethod", is("orcid")))
|
||||
.andExpect(jsonPath("$.type", is("status")))
|
||||
.andExpect(cookie().doesNotExist("DSPACE-XSRF-COOKIE"))
|
||||
.andExpect(header().doesNotExist("DSPACE-XSRF-TOKEN"));
|
||||
|
||||
String headerToken = getClient().perform(post("/api/authn/login").header("Origin", uiURL)
|
||||
.secure(true)
|
||||
.cookie(authCookie))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(cookie().value(AUTHORIZATION_COOKIE, ""))
|
||||
.andExpect(header().exists(AUTHORIZATION_HEADER))
|
||||
.andExpect(cookie().exists("DSPACE-XSRF-COOKIE"))
|
||||
.andExpect(header().exists("DSPACE-XSRF-TOKEN"))
|
||||
.andReturn().getResponse()
|
||||
.getHeader(AUTHORIZATION_HEADER).replace(AUTHORIZATION_TYPE, "");
|
||||
|
||||
assertTrue("Check tokens " + token + " and " + headerToken + " have same claims",
|
||||
tokenClaimsEqual(token, headerToken));
|
||||
|
||||
getClient(headerToken).perform(get("/api/authn/status").header("Origin", uiURL))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$.okay", is(true)))
|
||||
.andExpect(jsonPath("$.authenticated", is(true)))
|
||||
.andExpect(jsonPath("$.authenticationMethod", is("orcid")))
|
||||
.andExpect(jsonPath("$.type", is("status")));
|
||||
|
||||
getClient(headerToken).perform(post("/api/authn/logout").header("Origin", uiURL))
|
||||
.andExpect(status().isNoContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOrcidLoginURL() throws Exception {
|
||||
|
||||
configurationService.setProperty("plugin.sequence.org.dspace.authenticate.AuthenticationMethod", ORCID_ONLY);
|
||||
|
||||
String originalClientId = orcidConfiguration.getClientId();
|
||||
orcidConfiguration.setClientId("CLIENT-ID");
|
||||
|
||||
try {
|
||||
|
||||
getClient().perform(post("/api/authn/login"))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string("WWW-Authenticate",
|
||||
"orcid realm=\"DSpace REST API\", " +
|
||||
"location=\"https://orcid.org//oauth/authorize?client_id=CLIENT-ID&response_type=code"
|
||||
+ "&scope=/authenticate+/read-limited+/activities/update+/person/update&redirect_uri"
|
||||
+ "=http%3A%2F%2Flocalhost%2Fapi%2Fauthn%2Forcid\""));
|
||||
|
||||
} finally {
|
||||
orcidConfiguration.setClientId(originalClientId);
|
||||
}
|
||||
}
|
||||
|
||||
// Get a short-lived token based on an active login token
|
||||
private String getShortLivedToken(String loginToken) throws Exception {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
@@ -1591,5 +1715,15 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private OrcidTokenResponseDTO buildOrcidTokenResponse(String orcid, String accessToken) {
|
||||
OrcidTokenResponseDTO token = new OrcidTokenResponseDTO();
|
||||
token.setAccessToken(accessToken);
|
||||
token.setOrcid(orcid);
|
||||
token.setTokenType("Bearer");
|
||||
token.setName("Test User");
|
||||
token.setScope(String.join(" ", new String[] { "FirstScope", "SecondScope" }));
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -40,6 +40,7 @@ import org.dspace.app.orcid.client.OrcidClient;
|
||||
import org.dspace.app.orcid.exception.OrcidClientException;
|
||||
import org.dspace.app.orcid.model.OrcidTokenResponseDTO;
|
||||
import org.dspace.app.rest.model.AuthnRest;
|
||||
import org.dspace.app.rest.security.OrcidLoginFilter;
|
||||
import org.dspace.app.rest.security.jwt.EPersonClaimProvider;
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.dspace.authenticate.OrcidAuthenticationBean;
|
||||
@@ -67,12 +68,14 @@ import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link OrcidAuthenticationRestController}.
|
||||
* Integration tests for {@link OrcidLoginFilter}.
|
||||
*
|
||||
* @author Luca Giamminonni (luca.giamminonni at 4science.it)
|
||||
*
|
||||
*/
|
||||
public class OrcidAuthenticationRestControllerIT extends AbstractControllerIntegrationTest {
|
||||
public class OrcidLoginFilterIT extends AbstractControllerIntegrationTest {
|
||||
|
||||
public static final String[] PASSWORD_ONLY = { "org.dspace.authenticate.PasswordAuthentication" };
|
||||
|
||||
private final static String ORCID = "0000-1111-2222-3333";
|
||||
private final static String CODE = "123456";
|
||||
@@ -119,6 +122,15 @@ public class OrcidAuthenticationRestControllerIT extends AbstractControllerInteg
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoRedirectIfOrcidDisabled() throws Exception {
|
||||
configurationService.setProperty("plugin.sequence.org.dspace.authenticate.AuthenticationMethod", PASSWORD_ONLY);
|
||||
|
||||
getClient().perform(get("/api/" + AuthnRest.CATEGORY + "/orcid")
|
||||
.param("code", CODE))
|
||||
.andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEPersonCreationViaOrcidLogin() throws Exception {
|
||||
|
||||
@@ -436,6 +448,65 @@ public class OrcidAuthenticationRestControllerIT extends AbstractControllerInteg
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRedirectToGivenTrustedUrl() throws Exception {
|
||||
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
EPersonBuilder.createEPerson(context)
|
||||
.withEmail("test@email.it")
|
||||
.withNetId(ORCID)
|
||||
.withNameInMetadata("Test", "User")
|
||||
.withCanLogin(true)
|
||||
.build();
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
when(orcidClientMock.getAccessToken(CODE)).thenReturn(buildOrcidTokenResponse(ORCID, ACCESS_TOKEN));
|
||||
|
||||
String token = getClient().perform(get("/api/" + AuthnRest.CATEGORY + "/orcid")
|
||||
.param("redirectUrl", "http://localhost:8080/server/api/authn/status")
|
||||
.param("code", CODE))
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.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("orcid")));
|
||||
|
||||
verify(orcidClientMock).getAccessToken(CODE);
|
||||
verifyNoMoreInteractions(orcidClientMock);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRedirectToGivenUntrustedUrl() throws Exception {
|
||||
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
EPersonBuilder.createEPerson(context)
|
||||
.withEmail("test@email.it")
|
||||
.withNetId(ORCID)
|
||||
.withNameInMetadata("Test", "User")
|
||||
.withCanLogin(true)
|
||||
.build();
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
when(orcidClientMock.getAccessToken(CODE)).thenReturn(buildOrcidTokenResponse(ORCID, ACCESS_TOKEN));
|
||||
|
||||
getClient().perform(get("/api/" + AuthnRest.CATEGORY + "/orcid")
|
||||
.param("redirectUrl", "http://dspace.org")
|
||||
.param("code", CODE))
|
||||
.andExpect(status().isBadRequest());
|
||||
|
||||
verify(orcidClientMock).getAccessToken(CODE);
|
||||
verifyNoMoreInteractions(orcidClientMock);
|
||||
|
||||
}
|
||||
|
||||
private OrcidTokenResponseDTO buildOrcidTokenResponse(String orcid, String accessToken) {
|
||||
OrcidTokenResponseDTO token = new OrcidTokenResponseDTO();
|
||||
token.setAccessToken(accessToken);
|
Reference in New Issue
Block a user