From 8791537e6f22ae750ed2c024b0796bd3c58a43cb Mon Sep 17 00:00:00 2001 From: Vincent Paturet <46598384+vpaturet@users.noreply.github.com> Date: Mon, 10 Jun 2024 09:59:45 +0200 Subject: [PATCH] Retrofit Entur authorization service (#340) * Retrofit Entur authorization service * Code cleanup --- .../security/EnturUserContextServiceTest.java | 4 +- .../security/EnturSecurityConfiguration.java | 26 +++++-- .../security/EnturUserContextService.java | 73 +++++-------------- .../config/MockedRoleAssignmentExtractor.java | 62 ---------------- .../config/RoleAssignmentListBuilder.java | 57 --------------- 5 files changed, 41 insertions(+), 181 deletions(-) delete mode 100644 src/test/java/no/entur/uttu/config/MockedRoleAssignmentExtractor.java delete mode 100644 src/test/java/no/entur/uttu/config/RoleAssignmentListBuilder.java diff --git a/src/ext-test/java/no/entur/uttu/ext/entur/security/EnturUserContextServiceTest.java b/src/ext-test/java/no/entur/uttu/ext/entur/security/EnturUserContextServiceTest.java index 5aa989f8..43dd910b 100644 --- a/src/ext-test/java/no/entur/uttu/ext/entur/security/EnturUserContextServiceTest.java +++ b/src/ext-test/java/no/entur/uttu/ext/entur/security/EnturUserContextServiceTest.java @@ -6,6 +6,7 @@ import no.entur.uttu.model.Provider; import no.entur.uttu.repository.ProviderRepository; import org.entur.oauth2.JwtRoleAssignmentExtractor; +import org.entur.oauth2.user.JwtUserInfoExtractor; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -30,7 +31,8 @@ void setUp() { subject = new EnturUserContextService( mockProviderRepository, - new JwtRoleAssignmentExtractor() + new JwtRoleAssignmentExtractor(), + new JwtUserInfoExtractor() ); } diff --git a/src/ext/java/no/entur/uttu/ext/entur/security/EnturSecurityConfiguration.java b/src/ext/java/no/entur/uttu/ext/entur/security/EnturSecurityConfiguration.java index c1010cd4..09d4fa72 100644 --- a/src/ext/java/no/entur/uttu/ext/entur/security/EnturSecurityConfiguration.java +++ b/src/ext/java/no/entur/uttu/ext/entur/security/EnturSecurityConfiguration.java @@ -6,7 +6,9 @@ import org.entur.oauth2.JwtRoleAssignmentExtractor; import org.entur.oauth2.RorAuthenticationConverter; import org.entur.oauth2.multiissuer.MultiIssuerAuthenticationManagerResolverBuilder; +import org.entur.oauth2.user.JwtUserInfoExtractor; import org.rutebanken.helper.organisation.RoleAssignmentExtractor; +import org.rutebanken.helper.organisation.user.UserInfoExtractor; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -24,16 +26,26 @@ public JwtAuthenticationConverter customJwtAuthenticationConverter() { } @Bean - public UserContextService userContextService( - ProviderRepository providerRepository, - RoleAssignmentExtractor roleAssignmentExtractor - ) { - return new EnturUserContextService(providerRepository, roleAssignmentExtractor); + public RoleAssignmentExtractor roleAssignmentExtractor() { + return new JwtRoleAssignmentExtractor(); } @Bean - public RoleAssignmentExtractor roleAssignmentExtractor() { - return new JwtRoleAssignmentExtractor(); + public UserInfoExtractor userInfoExtractor() { + return new JwtUserInfoExtractor(); + } + + @Bean + public UserContextService userContextService( + ProviderRepository providerRepository, + RoleAssignmentExtractor roleAssignmentExtractor, + UserInfoExtractor userInfoExtractor + ) { + return new EnturUserContextService( + providerRepository, + roleAssignmentExtractor, + userInfoExtractor + ); } @Bean diff --git a/src/ext/java/no/entur/uttu/ext/entur/security/EnturUserContextService.java b/src/ext/java/no/entur/uttu/ext/entur/security/EnturUserContextService.java index c059e8be..a55d5a99 100644 --- a/src/ext/java/no/entur/uttu/ext/entur/security/EnturUserContextService.java +++ b/src/ext/java/no/entur/uttu/ext/entur/security/EnturUserContextService.java @@ -1,85 +1,50 @@ package no.entur.uttu.ext.entur.security; -import static org.rutebanken.helper.organisation.AuthorizationConstants.ROLE_ROUTE_DATA_ADMIN; -import static org.rutebanken.helper.organisation.AuthorizationConstants.ROLE_ROUTE_DATA_EDIT; - -import java.util.List; import no.entur.uttu.model.Provider; import no.entur.uttu.repository.ProviderRepository; import no.entur.uttu.security.spi.UserContextService; -import org.rutebanken.helper.organisation.RoleAssignment; import org.rutebanken.helper.organisation.RoleAssignmentExtractor; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.oauth2.jwt.Jwt; -import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; +import org.rutebanken.helper.organisation.authorization.AuthorizationService; +import org.rutebanken.helper.organisation.authorization.DefaultAuthorizationService; +import org.rutebanken.helper.organisation.user.UserInfoExtractor; public class EnturUserContextService implements UserContextService { private final ProviderRepository providerRepository; - - private final RoleAssignmentExtractor roleAssignmentExtractor; + private final AuthorizationService authorizationService; + private final UserInfoExtractor userInfoExtractor; public EnturUserContextService( ProviderRepository providerRepository, - RoleAssignmentExtractor roleAssignmentExtractor + RoleAssignmentExtractor roleAssignmentExtractor, + UserInfoExtractor userInfoExtractor ) { this.providerRepository = providerRepository; - this.roleAssignmentExtractor = roleAssignmentExtractor; + this.userInfoExtractor = userInfoExtractor; + authorizationService = + new DefaultAuthorizationService<>( + this::getProviderCodespaceByProviderCode, + roleAssignmentExtractor + ); } @Override public String getPreferredName() { - Authentication auth = SecurityContextHolder.getContext().getAuthentication(); - JwtAuthenticationToken jwtAuthenticationToken = (JwtAuthenticationToken) auth; - Jwt jwt = (Jwt) jwtAuthenticationToken.getPrincipal(); - return jwt.getClaimAsString("https://ror.entur.io/preferred_name"); + return userInfoExtractor.getPreferredName(); } @Override public boolean isAdmin() { - Authentication auth = SecurityContextHolder.getContext().getAuthentication(); - List roleAssignments = - roleAssignmentExtractor.getRoleAssignmentsForUser(auth); - - return roleAssignments - .stream() - .anyMatch(roleAssignment -> - roleAssignment.getRole().equals(ROLE_ROUTE_DATA_ADMIN) && - roleAssignment.getOrganisation().equals("RB") - ); + return authorizationService.isRouteDataAdmin(); } @Override public boolean hasAccessToProvider(String providerCode) { - if (providerCode == null) { - return false; - } - Provider provider = providerRepository.getOne(providerCode); - if (provider == null) { - return false; - } - - Authentication auth = SecurityContextHolder.getContext().getAuthentication(); - - List roleAssignments = - roleAssignmentExtractor.getRoleAssignmentsForUser(auth); - - return roleAssignments - .stream() - .anyMatch(roleAssignment -> - ( - roleAssignment.getRole().equals(ROLE_ROUTE_DATA_ADMIN) && - roleAssignment.getOrganisation().equals("RB") - ) || - match(roleAssignment, ROLE_ROUTE_DATA_EDIT, provider) - ); + return authorizationService.canEditRouteData(providerCode); } - private boolean match(RoleAssignment roleAssignment, String role, Provider provider) { - return ( - role.equals(roleAssignment.getRole()) && - provider.getCodespace().getXmlns().equals(roleAssignment.getOrganisation()) - ); + private String getProviderCodespaceByProviderCode(String providerCode) { + Provider provider = providerRepository.getOne(providerCode); + return provider == null ? null : provider.getCodespace().getXmlns(); } } diff --git a/src/test/java/no/entur/uttu/config/MockedRoleAssignmentExtractor.java b/src/test/java/no/entur/uttu/config/MockedRoleAssignmentExtractor.java deleted file mode 100644 index cda38f56..00000000 --- a/src/test/java/no/entur/uttu/config/MockedRoleAssignmentExtractor.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Licensed under the EUPL, Version 1.2 or – as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * - * https://joinup.ec.europa.eu/software/page/eupl - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - */ - -package no.entur.uttu.config; - -import java.util.Arrays; -import java.util.List; -import org.rutebanken.helper.organisation.RoleAssignment; -import org.rutebanken.helper.organisation.RoleAssignmentExtractor; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Service; - -/** - * For assigned user roles in integration tests. Defaults to full access. - */ -@Service -public class MockedRoleAssignmentExtractor implements RoleAssignmentExtractor { - - private List nextReturnedRoleAssignmentList; - - @Override - public List getRoleAssignmentsForUser() { - List returnValue = nextReturnedRoleAssignmentList; - - if (returnValue == null) { - returnValue = RoleAssignmentListBuilder.builder().withAccessAllAreas().build(); - } - - return returnValue; - } - - @Override - public List getRoleAssignmentsForUser(Authentication authentication) { - return getRoleAssignmentsForUser(); - } - - public void setNextReturnedRoleAssignment( - List nextReturnedRoleAssignmentList - ) { - this.nextReturnedRoleAssignmentList = nextReturnedRoleAssignmentList; - } - - public void setNextReturnedRoleAssignment(RoleAssignment roleAssignment) { - this.nextReturnedRoleAssignmentList = Arrays.asList(roleAssignment); - } - - public void reset() { - nextReturnedRoleAssignmentList = null; - } -} diff --git a/src/test/java/no/entur/uttu/config/RoleAssignmentListBuilder.java b/src/test/java/no/entur/uttu/config/RoleAssignmentListBuilder.java deleted file mode 100644 index 90a03fb9..00000000 --- a/src/test/java/no/entur/uttu/config/RoleAssignmentListBuilder.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Licensed under the EUPL, Version 1.2 or – as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * - * https://joinup.ec.europa.eu/software/page/eupl - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - */ - -package no.entur.uttu.config; - -import java.util.ArrayList; -import java.util.List; -import org.rutebanken.helper.organisation.AuthorizationConstants; -import org.rutebanken.helper.organisation.RoleAssignment; - -public class RoleAssignmentListBuilder { - - private List roleAssignments = new ArrayList<>(); - - public static RoleAssignmentListBuilder builder() { - return new RoleAssignmentListBuilder(); - } - - public List build() { - return roleAssignments; - } - - public RoleAssignmentListBuilder withAccessAllAreas() { - return withRole( - AuthorizationConstants.ROLE_EDIT_STOPS, - AuthorizationConstants.ENTITY_CLASSIFIER_ALL_TYPES - ) - .withRole( - AuthorizationConstants.ROLE_DELETE_STOPS, - AuthorizationConstants.ENTITY_CLASSIFIER_ALL_TYPES - ); - } - - private RoleAssignmentListBuilder withRole(String roleName, String entityType) { - RoleAssignment roleAssignment = RoleAssignment - .builder() - .withRole(roleName) - .withOrganisation("NOT_YET_CHECKED") - .withEntityClassification(AuthorizationConstants.ENTITY_TYPE, entityType) - .build(); - - roleAssignments.add(roleAssignment); - return this; - } -}