From 3f144d14e4a731e7473c5897e3dd70e2c8f55c52 Mon Sep 17 00:00:00 2001 From: AndiBuls Date: Mon, 16 Mar 2020 15:16:43 +0100 Subject: [PATCH 1/4] update KeyCloakConfig like in the KeycloakDemo Co-authored-by: LukasEttel Co-authored-by: AndiBuls --- build.gradle | 9 ++++- .../gruppen2/controller/APIController.java | 2 + .../controller/Gruppen2Controller.java | 3 ++ .../gruppen2/security/KeycloakConfig.java | 36 ++++++++++++++++++ .../mops/gruppen2/service/EventService.java | 38 ++++++++++--------- src/main/resources/application-dev.properties | 11 +++++- src/main/resources/application.properties | 3 +- 7 files changed, 80 insertions(+), 22 deletions(-) diff --git a/build.gradle b/build.gradle index c61339b..25ea948 100644 --- a/build.gradle +++ b/build.gradle @@ -59,9 +59,11 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' - + + compile group: 'org.springframework.boot', name: 'spring-boot-starter-oauth2-client', version: '2.2.5.RELEASE' + implementation 'org.keycloak:keycloak-spring-boot-starter:9.0.0' - implementation 'org.keycloak.bom:keycloak-adapter-bom:3.3.0.Final' + implementation 'org.keycloak.bom:keycloak-adapter-bom:9.0.0' implementation 'mops:styleguide:2.1.0' implementation 'io.springfox:springfox-swagger2:2.9.2' implementation 'io.springfox:springfox-swagger-ui:2.9.2' @@ -73,6 +75,8 @@ dependencies { runtimeOnly 'com.h2database:h2' runtimeOnly 'mysql:mysql-connector-java' + compile group: 'org.springframework.security.oauth', name: 'spring-security-oauth2', version: '2.4.0.RELEASE' + testImplementation 'org.assertj:assertj-core:3.15.0' testImplementation('org.springframework.boot:spring-boot-starter-test') { exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' @@ -80,6 +84,7 @@ dependencies { testImplementation 'org.springframework.security:spring-security-test' testImplementation 'com.tngtech.archunit:archunit-junit5:0.13.1' implementation 'junit:junit:4.12' + implementation 'junit:junit:4.12' } test { diff --git a/src/main/java/mops/gruppen2/controller/APIController.java b/src/main/java/mops/gruppen2/controller/APIController.java index f4d18ef..4e96405 100644 --- a/src/main/java/mops/gruppen2/controller/APIController.java +++ b/src/main/java/mops/gruppen2/controller/APIController.java @@ -11,6 +11,7 @@ import mops.gruppen2.service.APIFormatterService; import mops.gruppen2.service.EventService; import mops.gruppen2.service.GroupService; import mops.gruppen2.service.SerializationService; +import org.springframework.security.access.annotation.Secured; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -33,6 +34,7 @@ public class APIController { } @GetMapping("/updateGroups/{status}") + @Secured("ROLE_api_user") @ApiOperation(value = "Gibt alle Gruppen zurück in denen sich etwas geändert hat") public UpdatedGroupRequestMapper updateGroup(@ApiParam("Letzter Status des Anfragestellers") @PathVariable Long status) throws EventException { List events = eventService.getNewEvents(status); diff --git a/src/main/java/mops/gruppen2/controller/Gruppen2Controller.java b/src/main/java/mops/gruppen2/controller/Gruppen2Controller.java index c71ae8d..32ac563 100644 --- a/src/main/java/mops/gruppen2/controller/Gruppen2Controller.java +++ b/src/main/java/mops/gruppen2/controller/Gruppen2Controller.java @@ -14,6 +14,7 @@ import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; +import org.springframework.web.client.RestTemplate; import org.springframework.web.server.ResponseStatusException; import javax.annotation.security.RolesAllowed; @@ -27,6 +28,8 @@ public class Gruppen2Controller { @Autowired Gruppen2Config gruppen2Config; + @Autowired + RestTemplate serviceAccountRestTemplate; private final KeyCloakService keyCloakService; private final EventService eventService; diff --git a/src/main/java/mops/gruppen2/security/KeycloakConfig.java b/src/main/java/mops/gruppen2/security/KeycloakConfig.java index 57032ab..d707be1 100644 --- a/src/main/java/mops/gruppen2/security/KeycloakConfig.java +++ b/src/main/java/mops/gruppen2/security/KeycloakConfig.java @@ -1,8 +1,13 @@ package mops.gruppen2.security; +import org.keycloak.OAuth2Constants; import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; +import org.springframework.web.client.RestTemplate; /** * WORKAROUND for https://issues.redhat.com/browse/KEYCLOAK-11282 @@ -15,4 +20,35 @@ public class KeycloakConfig { public KeycloakSpringBootConfigResolver keycloakConfigResolver() { return new KeycloakSpringBootConfigResolver(); } + + @Value("${keycloak.resource}") + + private String clientId; + + @Value("${keycloak.credentials.secret}") + + private String clientSecret; + + @Value("${hhu_keycloak.token-uri}") + + private String tokenUri; + + + @Bean + public RestTemplate serviceAccountRestTemplate() { + + ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails(); + + resourceDetails.setGrantType(OAuth2Constants.CLIENT_CREDENTIALS); + + resourceDetails.setAccessTokenUri(tokenUri); + + resourceDetails.setClientId(clientId); + + resourceDetails.setClientSecret(clientSecret); + + + return new OAuth2RestTemplate(resourceDetails); + + } } \ No newline at end of file diff --git a/src/main/java/mops/gruppen2/service/EventService.java b/src/main/java/mops/gruppen2/service/EventService.java index 2bce156..2c4b709 100644 --- a/src/main/java/mops/gruppen2/service/EventService.java +++ b/src/main/java/mops/gruppen2/service/EventService.java @@ -23,17 +23,19 @@ public class EventService { this.eventStore = eventStore; } - /** sichert ein Event Objekt indem es ein EventDTO Objekt erzeugt + /** + * sichert ein Event Objekt indem es ein EventDTO Objekt erzeugt * * @param event */ - public void saveEvent(Event event){ + public void saveEvent(Event event) { EventDTO eventDTO = getDTO(event); eventStore.save(eventDTO); } - /** Erzeugt aus einem Event Objekt ein EventDTO Objekt. - * Ist die Gruppe öffentlich, dann wird die visibility auf true gesetzt. + /** + * Erzeugt aus einem Event Objekt ein EventDTO Objekt. + * Ist die Gruppe öffentlich, dann wird die visibility auf true gesetzt. * * @param event * @return EventDTO @@ -42,24 +44,24 @@ public class EventService { EventDTO eventDTO = new EventDTO(); eventDTO.setGroup_id(event.getGroup_id()); eventDTO.setUser_id(event.getUser_id()); - if(event instanceof CreateGroupEvent) { - if(((CreateGroupEvent) event).getGroupVisibility() == Visibility.PRIVATE) { + if (event instanceof CreateGroupEvent) { + if (((CreateGroupEvent) event).getGroupVisibility() == Visibility.PRIVATE) { eventDTO.setVisibility(false); - }else { + } else { eventDTO.setVisibility(true); } } - try { eventDTO.setEvent_payload(serializationService.serializeEvent(event)); } catch (JsonProcessingException e) { e.printStackTrace(); } - return eventDTO; + return eventDTO; } - /** Sorgt dafür die Group_id immer um 1 zu erhöhen + /** + * Sorgt dafür die Group_id immer um 1 zu erhöhen * * @return Gibt Long zurück */ @@ -77,30 +79,32 @@ public class EventService { return tmpId; } - /** Findet alle Events welche ab dem neuen Status hinzugekommen sind + /** + * Findet alle Events welche ab dem neuen Status hinzugekommen sind * * @param status * @return Liste von Events */ - public List getNewEvents(Long status){ + public List getNewEvents(Long status) { List groupIdsThatChanged = eventStore.findNewEventSinceStatus(status); List groupEventDTOS = eventStore.findAllEventsOfGroups(groupIdsThatChanged); return translateEventDTOs(groupEventDTOS); } - /** Erzeugt aus einer Liste von eventDTOs eine Liste von Events + /** + * Erzeugt aus einer Liste von eventDTOs eine Liste von Events * * @param eventDTOS * @return Liste von Events */ - public List translateEventDTOs(Iterable eventDTOS){ + public List translateEventDTOs(Iterable eventDTOS) { List events = new ArrayList<>(); for (EventDTO eventDTO : eventDTOS) { try { events.add(serializationService.deserializeEvent(eventDTO.getEvent_payload())); - }catch (JsonProcessingException e) { + } catch (JsonProcessingException e) { e.printStackTrace(); } } @@ -113,12 +117,12 @@ public class EventService { * @param createGroupEvents Liste von Event Objekten */ public void saveEventList(List createGroupEvents) { - for(Event event : createGroupEvents) { + for (Event event : createGroupEvents) { saveEvent(event); } } - public Long getMaxEvent_id(){ + public Long getMaxEvent_id() { return eventStore.getHighesEvent_ID(); } diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index 3ad4107..79a9404 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -12,5 +12,12 @@ spring.jpa.database-platform=org.hibernate.dialect.H2Dialect keycloak.principal-attribute=preferred_username keycloak.auth-server-url=https://keycloak.cs.hhu.de/auth keycloak.realm=MOPS -keycloak.resource=demo -keycloak.public-client=true + +hhu_keycloak.token-uri=https://keycloak.cs.hhu.de/auth/realms/MOPS/protocol/openid-connect/token +keycloak.resource=gruppenfindung +keycloak.credentials.secret= fc6ebf10-8c63-4e71-a667-4eae4e8209a1 +keycloak.verify-token-audience=true +keycloak.use-resource-role-mappings=true + +keycloak.autodetect-bearer-only=true +keycloak.confidential-port= 443 \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 257b306..7f0e7ec 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,2 @@ -spring.profiles.active=dev \ No newline at end of file +spring.profiles.active=dev + From e12f0c1d59d7d6bb2caea274dcdee2af18221830 Mon Sep 17 00:00:00 2001 From: "[Mahgs]" Date: Mon, 16 Mar 2020 15:40:46 +0100 Subject: [PATCH 2/4] added @Secured and fixed Co-authored-by: LukasEttel Co-authored-by: AndiBuls --- src/main/java/mops/gruppen2/controller/APIController.java | 3 +++ .../java/mops/gruppen2/controller/Gruppen2Controller.java | 6 +----- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/mops/gruppen2/controller/APIController.java b/src/main/java/mops/gruppen2/controller/APIController.java index 4e96405..7e1e63b 100644 --- a/src/main/java/mops/gruppen2/controller/APIController.java +++ b/src/main/java/mops/gruppen2/controller/APIController.java @@ -44,12 +44,15 @@ public class APIController { } @GetMapping("/getGroupIdsOfUser/{teilnehmer}") + @Secured("ROLE_api_user") + @ApiOperation(value = "Gibt alle Gruppen zurück in denen sich ein Teilnehmer befindet") public List getGroupsOfUser(@ApiParam("Teilnehmer dessen groupIds zurückgegeben werden sollen") @PathVariable String teilnehmer) throws EventException { return eventService.getGroupsOfUser(teilnehmer); } @GetMapping("/getGroup/{groupId}") + @Secured("ROLE_api_user") @ApiOperation(value = "Gibt die Gruppe mit der als Parameter mitgegebenden groupId zurück") public Group getGroupFromId(@ApiParam("GruppenId der gefordeten Gruppe") @PathVariable Long groupId) throws EventException{ List eventList = eventService.getEventsOfGroup(groupId); diff --git a/src/main/java/mops/gruppen2/controller/Gruppen2Controller.java b/src/main/java/mops/gruppen2/controller/Gruppen2Controller.java index 32ac563..36cd403 100644 --- a/src/main/java/mops/gruppen2/controller/Gruppen2Controller.java +++ b/src/main/java/mops/gruppen2/controller/Gruppen2Controller.java @@ -3,8 +3,7 @@ package mops.gruppen2.controller; import mops.gruppen2.config.Gruppen2Config; import mops.gruppen2.domain.Exceptions.EventException; import mops.gruppen2.domain.Group; -import mops.gruppen2.domain.GroupType; -import mops.gruppen2.domain.Role; + import mops.gruppen2.domain.User; import mops.gruppen2.security.Account; import mops.gruppen2.service.*; @@ -20,7 +19,6 @@ import org.springframework.web.server.ResponseStatusException; import javax.annotation.security.RolesAllowed; import java.util.ArrayList; import java.util.List; -import java.util.Set; @Controller @RequestMapping("/gruppen2") @@ -28,8 +26,6 @@ public class Gruppen2Controller { @Autowired Gruppen2Config gruppen2Config; - @Autowired - RestTemplate serviceAccountRestTemplate; private final KeyCloakService keyCloakService; private final EventService eventService; From 7e2c1dec8105717a1e5b359f819e2023f0cc7c9e Mon Sep 17 00:00:00 2001 From: "[Mahgs]" Date: Mon, 16 Mar 2020 16:16:46 +0100 Subject: [PATCH 3/4] tested APIController Co-authored-by: AndiBuls Co-authored-by: Christoph --- src/main/java/mops/gruppen2/controller/APIController.java | 1 - src/main/java/mops/gruppen2/service/EventService.java | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/main/java/mops/gruppen2/controller/APIController.java b/src/main/java/mops/gruppen2/controller/APIController.java index 7e1e63b..12591a1 100644 --- a/src/main/java/mops/gruppen2/controller/APIController.java +++ b/src/main/java/mops/gruppen2/controller/APIController.java @@ -45,7 +45,6 @@ public class APIController { @GetMapping("/getGroupIdsOfUser/{teilnehmer}") @Secured("ROLE_api_user") - @ApiOperation(value = "Gibt alle Gruppen zurück in denen sich ein Teilnehmer befindet") public List getGroupsOfUser(@ApiParam("Teilnehmer dessen groupIds zurückgegeben werden sollen") @PathVariable String teilnehmer) throws EventException { return eventService.getGroupsOfUser(teilnehmer); diff --git a/src/main/java/mops/gruppen2/service/EventService.java b/src/main/java/mops/gruppen2/service/EventService.java index 2c4b709..d6fb3da 100644 --- a/src/main/java/mops/gruppen2/service/EventService.java +++ b/src/main/java/mops/gruppen2/service/EventService.java @@ -2,8 +2,6 @@ package mops.gruppen2.service; import com.fasterxml.jackson.core.JsonProcessingException; import mops.gruppen2.domain.EventDTO; -import mops.gruppen2.domain.Exceptions.EventException; -import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Visibility; import mops.gruppen2.domain.event.CreateGroupEvent; import mops.gruppen2.domain.event.Event; From 6c8a5fbe78463e324392e9aec2de90d5359e4366 Mon Sep 17 00:00:00 2001 From: "[Mahgs]" Date: Mon, 16 Mar 2020 16:25:04 +0100 Subject: [PATCH 4/4] changed docker.properties Co-authored-by: AndiBuls Co-authored-by: Christoph --- src/main/resources/application-docker.properties | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/resources/application-docker.properties b/src/main/resources/application-docker.properties index 99ee878..76fce96 100644 --- a/src/main/resources/application-docker.properties +++ b/src/main/resources/application-docker.properties @@ -10,5 +10,12 @@ spring.datasource.password=geheim keycloak.principal-attribute=preferred_username keycloak.auth-server-url=https://keycloak.cs.hhu.de/auth keycloak.realm=MOPS -keycloak.resource=demo -keycloak.public-client=true + +hhu_keycloak.token-uri=https://keycloak.cs.hhu.de/auth/realms/MOPS/protocol/openid-connect/token +keycloak.resource=gruppenfindung +keycloak.credentials.secret= fc6ebf10-8c63-4e71-a667-4eae4e8209a1 +keycloak.verify-token-audience=true +keycloak.use-resource-role-mappings=true + +keycloak.autodetect-bearer-only=true +keycloak.confidential-port= 443