From 683d4a71179a0f323b66d670915e4c7929e4a2f0 Mon Sep 17 00:00:00 2001 From: Okke Harsta Date: Sun, 15 Sep 2024 08:32:09 +0200 Subject: [PATCH] EduID integration --- server/src/main/java/access/eduid/EduID.java | 49 +++++++++++++++++++ .../java/access/eduid/EduIDProvision.java | 16 ++++++ server/src/main/resources/application.yml | 5 ++ .../src/test/java/access/eduid/EduIDTest.java | 47 ++++++++++++++++++ 4 files changed, 117 insertions(+) create mode 100644 server/src/main/java/access/eduid/EduID.java create mode 100644 server/src/main/java/access/eduid/EduIDProvision.java create mode 100644 server/src/test/java/access/eduid/EduIDTest.java diff --git a/server/src/main/java/access/eduid/EduID.java b/server/src/main/java/access/eduid/EduID.java new file mode 100644 index 00000000..be31e55e --- /dev/null +++ b/server/src/main/java/access/eduid/EduID.java @@ -0,0 +1,49 @@ +package access.eduid; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.*; +import org.springframework.http.client.support.BasicAuthenticationInterceptor; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import java.util.Collections; +import java.util.Optional; + +@Service +public class EduID { + + private static final Log LOG = LogFactory.getLog(EduID.class); + + private final String uri; + private final RestTemplate restTemplate; + private final HttpHeaders headers; + + public EduID(@Value("${myconext.uri}") String uri, + @Value("${myconext.username}") String userName, + @Value("${myconext.password}") String password) { + this.uri = uri; + this.restTemplate = new RestTemplate(); + this.restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(userName, password)); + this.headers = initHttpHeaders(); + } + + public Optional provisionEduid(EduIDProvision eduIDProvision) { + HttpEntity requestEntity = new HttpEntity<>(eduIDProvision, headers); + try { + ResponseEntity responseEntity = restTemplate.exchange(uri, HttpMethod.POST, requestEntity, EduIDProvision.class); + return Optional.of(responseEntity.getBody().getEduIDValue()); + } catch (RuntimeException e) { + LOG.error("Error in provisionEduid", e); + return Optional.empty(); + } + } + + private HttpHeaders initHttpHeaders() { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + return headers; + } +} diff --git a/server/src/main/java/access/eduid/EduIDProvision.java b/server/src/main/java/access/eduid/EduIDProvision.java new file mode 100644 index 00000000..81aa9073 --- /dev/null +++ b/server/src/main/java/access/eduid/EduIDProvision.java @@ -0,0 +1,16 @@ +package access.eduid; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + + +@Getter +@AllArgsConstructor +public class EduIDProvision { + + private String eduIDValue; + private String institutionGUID; + +} diff --git a/server/src/main/resources/application.yml b/server/src/main/resources/application.yml index 516d1cf6..b037969c 100644 --- a/server/src/main/resources/application.yml +++ b/server/src/main/resources/application.yml @@ -85,6 +85,11 @@ cron: metadata-resolver-fixed-rate-milliseconds: 86_400_000 metadata-resolver-url: "classpath:/metadata/idps-metadata.xml" +myconext: + uri: "https://login.test2.eduid.nl/myconext/api/invite/provision-eduid" + username: invite + password: secret + oidcng: discovery-url: "https://connect.test2.surfconext.nl/oidc/.well-known/openid-configuration" introspect-url: "https://connect.test2.surfconext.nl/oidc/introspect" diff --git a/server/src/test/java/access/eduid/EduIDTest.java b/server/src/test/java/access/eduid/EduIDTest.java new file mode 100644 index 00000000..12b9060e --- /dev/null +++ b/server/src/test/java/access/eduid/EduIDTest.java @@ -0,0 +1,47 @@ +package access.eduid; + +import access.WireMockExtension; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.SneakyThrows; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import java.util.Optional; +import java.util.UUID; + +import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class EduIDTest { + + private final ObjectMapper objectMapper = new ObjectMapper(); + private final EduID eduID = new EduID("http://localhost:8081/myconext/api/invite/provision-eduid", "invite", "secret"); + + @RegisterExtension + WireMockExtension mockServer = new WireMockExtension(8081); + + @SneakyThrows + @Test + void provisionEduid() { + String eduIDValue = UUID.randomUUID().toString(); + String institutionGUID = UUID.randomUUID().toString(); + EduIDProvision eduIDProvision = new EduIDProvision(eduIDValue, institutionGUID); + stubFor(post(urlPathMatching("/myconext/api/invite/provision-eduid")).willReturn(aResponse() + .withHeader("Content-Type", "application/json") + .withBody(objectMapper.writeValueAsString(eduIDProvision)))); + Optional eduid = eduID.provisionEduid(eduIDProvision); + assertEquals(eduIDProvision.getEduIDValue(), eduid.get()); + } + + @SneakyThrows + @Test + void provisionEduid404() { + EduIDProvision eduIDProvision = new EduIDProvision("eduIDValue", "institutionGUID"); + stubFor(post(urlPathMatching("/myconext/api/invite/provision-eduid")).willReturn(aResponse() + .withHeader("Content-Type", "application/json") + .withStatus(404))); + Optional eduid = eduID.provisionEduid(eduIDProvision); + assertTrue(eduid.isEmpty()); + } +} \ No newline at end of file