[CST-5669] Improved OrcidLoginFilter

This commit is contained in:
Luca Giamminonni
2022-05-13 16:52:40 +02:00
parent 4afa62a4c0
commit e22e53cc25
8 changed files with 343 additions and 115 deletions

View File

@@ -8,10 +8,12 @@
package org.dspace.authenticate; package org.dspace.authenticate;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Iterator;
import java.util.List; import java.util.List;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.dspace.authenticate.factory.AuthenticateServiceFactory;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.eperson.EPerson; import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group; import org.dspace.eperson.Group;
@@ -29,6 +31,26 @@ public class OrcidAuthentication implements AuthenticationMethod {
private final ServiceManager serviceManager = new DSpace().getServiceManager(); 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 @Override
public boolean canSelfRegister(Context context, HttpServletRequest request, String username) throws SQLException { public boolean canSelfRegister(Context context, HttpServletRequest request, String username) throws SQLException {
return getOrcidAuthentication().canSelfRegister(context, request, username); return getOrcidAuthentication().canSelfRegister(context, request, username);

View File

@@ -87,7 +87,7 @@ public class OrcidAuthenticationBean implements AuthenticationMethod {
LOGGER.warn("The incoming request has not code parameter"); LOGGER.warn("The incoming request has not code parameter");
return NO_SUCH_USER; return NO_SUCH_USER;
} }
request.setAttribute(ORCID_AUTH_ATTRIBUTE, true);
return authenticateWithOrcid(context, code, request); return authenticateWithOrcid(context, code, request);
} }

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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.");
}
}
}

View File

@@ -141,7 +141,7 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
LogoutFilter.class) LogoutFilter.class)
//Add a filter before our ORCID endpoints to do the authentication based on the data in the //Add a filter before our ORCID endpoints to do the authentication based on the data in the
// HTTP request // HTTP request
.addFilterBefore(new OrcidAuthenticationFilter("/api/authn/orcid", authenticationManager(), .addFilterBefore(new OrcidLoginFilter("/api/authn/orcid", authenticationManager(),
restAuthenticationService), restAuthenticationService),
LogoutFilter.class) LogoutFilter.class)
//Add a filter before our OIDC endpoints to do the authentication based on the data in the //Add a filter before our OIDC endpoints to do the authentication based on the data in the

View File

@@ -19,6 +19,8 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue; 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.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.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 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 com.nimbusds.jwt.SignedJWT;
import org.apache.commons.codec.CharEncoding; import org.apache.commons.codec.CharEncoding;
import org.apache.commons.io.IOUtils; 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.Authorization;
import org.dspace.app.rest.authorization.AuthorizationFeature; import org.dspace.app.rest.authorization.AuthorizationFeature;
import org.dspace.app.rest.authorization.AuthorizationFeatureService; 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.AuthorizationMatcher;
import org.dspace.app.rest.matcher.EPersonMatcher; import org.dspace.app.rest.matcher.EPersonMatcher;
import org.dspace.app.rest.matcher.HalMatcher; 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.model.EPersonRest;
import org.dspace.app.rest.projection.DefaultProjection; import org.dspace.app.rest.projection.DefaultProjection;
import org.dspace.app.rest.test.AbstractControllerIntegrationTest; import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
import org.dspace.app.rest.utils.Utils; import org.dspace.app.rest.utils.Utils;
import org.dspace.authenticate.OrcidAuthenticationBean;
import org.dspace.builder.BitstreamBuilder; import org.dspace.builder.BitstreamBuilder;
import org.dspace.builder.BundleBuilder; import org.dspace.builder.BundleBuilder;
import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CollectionBuilder;
@@ -93,11 +100,18 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
@Autowired @Autowired
private AuthorizationFeatureService authorizationFeatureService; private AuthorizationFeatureService authorizationFeatureService;
@Autowired
private OrcidConfiguration orcidConfiguration;
@Autowired
private OrcidAuthenticationBean orcidAuthentication;
@Autowired @Autowired
private Utils utils; private Utils utils;
public static final String[] PASS_ONLY = {"org.dspace.authenticate.PasswordAuthentication"}; public static final String[] PASS_ONLY = {"org.dspace.authenticate.PasswordAuthentication"};
public static final String[] SHIB_ONLY = {"org.dspace.authenticate.ShibAuthentication"}; 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 = { public static final String[] SHIB_AND_PASS = {
"org.dspace.authenticate.ShibAuthentication", "org.dspace.authenticate.ShibAuthentication",
"org.dspace.authenticate.PasswordAuthentication" "org.dspace.authenticate.PasswordAuthentication"
@@ -1495,6 +1509,116 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
.andExpect(status().isNoContent()); .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 // Get a short-lived token based on an active login token
private String getShortLivedToken(String loginToken) throws Exception { private String getShortLivedToken(String loginToken) throws Exception {
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
@@ -1591,5 +1715,15 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
return false; 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;
}
} }

View File

@@ -40,6 +40,7 @@ import org.dspace.app.orcid.client.OrcidClient;
import org.dspace.app.orcid.exception.OrcidClientException; import org.dspace.app.orcid.exception.OrcidClientException;
import org.dspace.app.orcid.model.OrcidTokenResponseDTO; import org.dspace.app.orcid.model.OrcidTokenResponseDTO;
import org.dspace.app.rest.model.AuthnRest; 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.security.jwt.EPersonClaimProvider;
import org.dspace.app.rest.test.AbstractControllerIntegrationTest; import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
import org.dspace.authenticate.OrcidAuthenticationBean; import org.dspace.authenticate.OrcidAuthenticationBean;
@@ -67,12 +68,14 @@ import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MvcResult; 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) * @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 ORCID = "0000-1111-2222-3333";
private final static String CODE = "123456"; 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 @Test
public void testEPersonCreationViaOrcidLogin() throws Exception { 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) { private OrcidTokenResponseDTO buildOrcidTokenResponse(String orcid, String accessToken) {
OrcidTokenResponseDTO token = new OrcidTokenResponseDTO(); OrcidTokenResponseDTO token = new OrcidTokenResponseDTO();
token.setAccessToken(accessToken); token.setAccessToken(accessToken);