diff --git a/token-checker-server/src/main/java/de/ozgcloud/token/TokenCheckerConfiguration.java b/token-checker-server/src/main/java/de/ozgcloud/token/TokenCheckerConfiguration.java index 00bce6c3068da62d39b1fa3682d1ce00d3631cd6..8d3ae5ad512f5951db840ac589d814c641b8b64e 100644 --- a/token-checker-server/src/main/java/de/ozgcloud/token/TokenCheckerConfiguration.java +++ b/token-checker-server/src/main/java/de/ozgcloud/token/TokenCheckerConfiguration.java @@ -28,16 +28,12 @@ import org.opensaml.core.config.InitializationService; import org.opensaml.core.xml.config.XMLObjectProviderRegistry; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.stereotype.Component; -import lombok.RequiredArgsConstructor; import net.shibboleth.utilities.java.support.component.ComponentInitializationException; import net.shibboleth.utilities.java.support.xml.BasicParserPool; import net.shibboleth.utilities.java.support.xml.ParserPool; -@Component @Configuration -@RequiredArgsConstructor public class TokenCheckerConfiguration { public static final String FEATURES_EXTERNAL_GENERAL_ENTITIES = "http://xml.org/sax/features/external-general-entities"; diff --git a/token-checker-server/src/main/java/de/ozgcloud/token/saml/SamlConfiguration.java b/token-checker-server/src/main/java/de/ozgcloud/token/saml/SamlConfiguration.java index a60ef4afd49332bf829ab78c291ddcb437c65476..50354cd7132d242953d9b1d308a1fdb19fc84452 100644 --- a/token-checker-server/src/main/java/de/ozgcloud/token/saml/SamlConfiguration.java +++ b/token-checker-server/src/main/java/de/ozgcloud/token/saml/SamlConfiguration.java @@ -18,6 +18,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import de.ozgcloud.token.TokenValidationProperties; +import de.ozgcloud.token.TokenValidationProperties.TokenValidationProperty; import lombok.RequiredArgsConstructor; import net.shibboleth.utilities.java.support.resolver.CriteriaSet; @@ -42,7 +43,7 @@ public class SamlConfiguration { return registryBuilder.build(); } - SamlTokenValidationService samlTokenService(TokenValidationProperties.TokenValidationProperty tokenValidationProperty) { + SamlTokenValidationService samlTokenService(TokenValidationProperty tokenValidationProperty) { return SamlTokenValidationService.builder() .signatureTrustEngine(samlTrustEngineFactory.buildSamlTrustEngine(tokenValidationProperty)) .decrypter(samlDecrypterFactory.buildDecrypter(tokenValidationProperty)) diff --git a/token-checker-server/src/main/java/de/ozgcloud/token/saml/SamlTokenValidationService.java b/token-checker-server/src/main/java/de/ozgcloud/token/saml/SamlTokenValidationService.java index ef3f560a365812966630d2de2b0e7293373321c7..e5120a5afc795e05dddca9cdcca651d6411180a4 100644 --- a/token-checker-server/src/main/java/de/ozgcloud/token/saml/SamlTokenValidationService.java +++ b/token-checker-server/src/main/java/de/ozgcloud/token/saml/SamlTokenValidationService.java @@ -25,6 +25,7 @@ package de.ozgcloud.token.saml; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -141,19 +142,36 @@ public class SamlTokenValidationService { } Set<TokenAttribute> buildTokenAttributes(Map<String, String> tokenAttributes, Response token) { - return adjustPostfachIdAttribute(tokenAttributes, token).entrySet().stream().map(this::buildTokenAttribute).collect(Collectors.toSet()); + return adjustAttributes(tokenAttributes, token).entrySet().stream().map(this::buildTokenAttribute).collect(Collectors.toSet()); + } + + Map<String, String> adjustAttributes(Map<String, String> tokenAttributes, Response token) { + return Collections.unmodifiableMap(adjustPostfachIdAttribute(replaceKeys(new HashMap<>(tokenAttributes)), token)); + } + + Map<String, String> replaceKeys(Map<String, String> tokenAttributes) { + tokenValidationProperty.getMappings().forEach((key, mappedKey) -> { + var attrValue = tokenAttributes.remove(mappedKey); + if (StringUtils.isNotBlank(attrValue)) { + tokenAttributes.put(key, attrValue); + } + }); + return tokenAttributes; } Map<String, String> adjustPostfachIdAttribute(Map<String, String> tokenAttributes, Response token) { - if (!tokenValidationProperty.isUseIdAsPostfachId()) { - return tokenAttributes; + if (tokenValidationProperty.isUseIdAsPostfachId()) { + tokenAttributes.put(TokenAttribute.POSTFACH_ID_KEY, token.getID()); } - var map = new HashMap<>(tokenAttributes); - map.put(TokenAttribute.POSTFACH_ID_KEY, token.getID()); - return map; + return tokenAttributes; } TokenAttribute buildTokenAttribute(Map.Entry<String, String> attribute) { - return TokenAttribute.builder().name(attribute.getKey()).value(attribute.getValue()).build(); + return TokenAttribute.builder().name(mapAttributeKey(attribute.getKey())).value(attribute.getValue()).build(); + } + + String mapAttributeKey(String key) { + return tokenValidationProperty.getMappings().entrySet().stream().filter(entry -> StringUtils.equals(entry.getValue(), key)) + .map(Map.Entry::getKey).findFirst().orElse(key); } } diff --git a/token-checker-server/src/test/java/de/ozgcloud/token/TokenAttributeTestFactory.java b/token-checker-server/src/test/java/de/ozgcloud/token/TokenAttributeTestFactory.java index 050d50edf052fd0437c9b2120edd27684ee2c451..a18272b442c68fff58524314f20fbf061cbe984b 100644 --- a/token-checker-server/src/test/java/de/ozgcloud/token/TokenAttributeTestFactory.java +++ b/token-checker-server/src/test/java/de/ozgcloud/token/TokenAttributeTestFactory.java @@ -23,6 +23,7 @@ */ package de.ozgcloud.token; +import java.util.HashMap; import java.util.Map; import com.thedeanda.lorem.LoremIpsum; @@ -43,6 +44,6 @@ public class TokenAttributeTestFactory { } public static Map<String, String> asMap() { - return Map.of(NAME, VALUE); + return new HashMap<>(Map.of(NAME, VALUE)); } } diff --git a/token-checker-server/src/test/java/de/ozgcloud/token/saml/SamlTokenValidationServiceTest.java b/token-checker-server/src/test/java/de/ozgcloud/token/saml/SamlTokenValidationServiceTest.java index 7998a5304cd09ea7ba9ca5148bfeb56040961b64..29a20fcfcc7033bd63ce0f1b50da28f2eb4ac22e 100644 --- a/token-checker-server/src/test/java/de/ozgcloud/token/saml/SamlTokenValidationServiceTest.java +++ b/token-checker-server/src/test/java/de/ozgcloud/token/saml/SamlTokenValidationServiceTest.java @@ -27,6 +27,7 @@ import static org.assertj.core.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; @@ -37,6 +38,8 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; @@ -435,15 +438,15 @@ class SamlTokenValidationServiceTest { @BeforeEach void init() { - doReturn(ADJUSTED_TOKEN_ATTRIBUTES_MAP).when(service).adjustPostfachIdAttribute(any(), any()); + doReturn(ADJUSTED_TOKEN_ATTRIBUTES_MAP).when(service).adjustAttributes(any(), any()); doReturn(TOKEN_ATTRIBUTE).when(service).buildTokenAttribute(any()); } @Test - void shouldCallAdjustPostfachIdAttribute() { + void shouldCallAdjustAttribute() { buildTokenAttributes(); - verify(service).adjustPostfachIdAttribute(TokenAttributeTestFactory.asMap(), token); + verify(service).adjustAttributes(TokenAttributeTestFactory.asMap(), token); } @Test @@ -465,6 +468,69 @@ class SamlTokenValidationServiceTest { } } + @Nested + class TestAdjustAttributes { + + private static final Map<String, String> TOKEN_ATTRIBUTES_MAP = TokenAttributeTestFactory.asMap(); + private static final Map<String, String> ADJUSTED_TOKEN_ATTRIBUTES_MAP = Map.of("key", "value"); + private static final Map<String, String> REPLACED_TOKEN_ATTRIBUTES_MAP = Map.of("key", "value"); + + @Mock + private Response token; + @Captor + private ArgumentCaptor<Map<String, String>> tokenAttributesCaptor; + + @BeforeEach + void init() { + when(service.replaceKeys(any())).thenReturn(REPLACED_TOKEN_ATTRIBUTES_MAP); + when(service.adjustPostfachIdAttribute(any(), any())).thenReturn(ADJUSTED_TOKEN_ATTRIBUTES_MAP); + } + + @Test + void shouldCallReplaceKeys() { + adjustAttributes(); + + verify(service).replaceKeys(tokenAttributesCaptor.capture()); + assertThat(tokenAttributesCaptor.getValue()).isEqualTo(TOKEN_ATTRIBUTES_MAP); + assertDoesNotThrow(() -> tokenAttributesCaptor.getValue().put("key", "value")); + } + + @Test + void shouldCallAdjustPostfachIdAttributes() { + adjustAttributes(); + + verify(service).adjustPostfachIdAttribute(REPLACED_TOKEN_ATTRIBUTES_MAP, token); + } + + @Test + void shouldReturnUnmodifiableMap() { + var result = adjustAttributes(); + + assertThat(result).isEqualTo(REPLACED_TOKEN_ATTRIBUTES_MAP); + Assertions.assertThrows(UnsupportedOperationException.class, () -> result.put("key", "value")); + } + + private Map<String, String> adjustAttributes() { + return service.adjustAttributes(TOKEN_ATTRIBUTES_MAP, token); + } + } + + @Nested + class TestReplaceKeys { + + private static final String MAPPING_KEY = LoremIpsum.getInstance().getWords(1); + + @Test + void shouldReplaceValue() { + when(tokenValidationProperty.getMappings()).thenReturn(Map.of(MAPPING_KEY, TokenAttributeTestFactory.NAME)); + + var result = service.replaceKeys(TokenAttributeTestFactory.asMap()); + + assertThat(result).containsOnly(Map.entry(MAPPING_KEY, TokenAttributeTestFactory.VALUE)); + } + + } + @Nested class TestAdjustPostfachIdAttribute { @@ -478,7 +544,7 @@ class SamlTokenValidationServiceTest { when(tokenValidationProperty.isUseIdAsPostfachId()).thenReturn(true); when(token.getID()).thenReturn(POSTFACH_ID); - var result = adjustPostfachIdAttribute(); + var result = service.adjustPostfachIdAttribute(TokenAttributeTestFactory.asMap(), token); assertThat(result).containsEntry(TokenAttribute.POSTFACH_ID_KEY, POSTFACH_ID); } @@ -486,7 +552,7 @@ class SamlTokenValidationServiceTest { @Test void shouldRewritePostfachId() { when(tokenValidationProperty.isUseIdAsPostfachId()).thenReturn(true); - var attributeMap = Map.of(TokenAttribute.POSTFACH_ID_KEY, LoremIpsum.getInstance().getWords(1)); + var attributeMap = new HashMap<>(Map.of(TokenAttribute.POSTFACH_ID_KEY, LoremIpsum.getInstance().getWords(1))); when(token.getID()).thenReturn(POSTFACH_ID); var result = service.adjustPostfachIdAttribute(attributeMap, token); @@ -503,10 +569,6 @@ class SamlTokenValidationServiceTest { assertThat(result).isEqualTo(attributeMap); } - - private Map<String, String> adjustPostfachIdAttribute() { - return service.adjustPostfachIdAttribute(TokenAttributeTestFactory.asMap(), token); - } } @Nested