diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ClaimTypeConverter.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ClaimTypeConverter.java index 06d2804408..a67a7a7a5d 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ClaimTypeConverter.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ClaimTypeConverter.java @@ -56,7 +56,10 @@ public final class ClaimTypeConverter implements Converter, this.claimTypeConverters.forEach((claimName, typeConverter) -> { if (claims.containsKey(claimName)) { Object claim = claims.get(claimName); - result.put(claimName, typeConverter.convert(claim)); + Object mappedClaim = typeConverter.convert(claim); + if (mappedClaim != null) { + result.put(claimName, mappedClaim); + } } }); return result; diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/converter/ClaimTypeConverterTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/converter/ClaimTypeConverterTests.java index 19544027cd..586ab8653a 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/converter/ClaimTypeConverterTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/converter/ClaimTypeConverterTests.java @@ -62,8 +62,6 @@ public class ClaimTypeConverterTests { private static final String JSON_OBJECT_CLAIM = "json-object-claim"; - private static final String NULL_OBJECT_CLAIM = "null-object-claim"; - private ClaimTypeConverter claimTypeConverter; @BeforeEach @@ -79,7 +77,6 @@ public class ClaimTypeConverterTests { TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(String.class))); Converter mapStringObjectConverter = getConverter(TypeDescriptor.map(Map.class, TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Object.class))); - Converter nullConverter = (value) -> null; Map> claimTypeConverters = new HashMap<>(); claimTypeConverters.put(STRING_CLAIM, stringConverter); claimTypeConverters.put(BOOLEAN_CLAIM, booleanConverter); @@ -88,7 +85,6 @@ public class ClaimTypeConverterTests { claimTypeConverters.put(COLLECTION_STRING_CLAIM, collectionStringConverter); claimTypeConverters.put(LIST_STRING_CLAIM, listStringConverter); claimTypeConverters.put(MAP_STRING_OBJECT_CLAIM, mapStringObjectConverter); - claimTypeConverters.put(NULL_OBJECT_CLAIM, nullConverter); this.claimTypeConverter = new ClaimTypeConverter(claimTypeConverters); } @@ -142,7 +138,6 @@ public class ClaimTypeConverterTests { claims.put(MAP_STRING_OBJECT_CLAIM, mapIntegerObject); claims.put(JSON_ARRAY_CLAIM, jsonArray); claims.put(JSON_OBJECT_CLAIM, jsonObject); - claims.put(NULL_OBJECT_CLAIM, instant.toString()); claims = this.claimTypeConverter.convert(claims); assertThat(claims.get(STRING_CLAIM)).isEqualTo("true"); assertThat(claims.get(BOOLEAN_CLAIM)).isEqualTo(Boolean.TRUE); @@ -153,7 +148,6 @@ public class ClaimTypeConverterTests { assertThat(claims.get(MAP_STRING_OBJECT_CLAIM)).isEqualTo(mapStringObject); assertThat(claims.get(JSON_ARRAY_CLAIM)).isEqualTo(jsonArrayListString); assertThat(claims.get(JSON_OBJECT_CLAIM)).isEqualTo(jsonObjectMap); - assertThat(claims.get(NULL_OBJECT_CLAIM)).isNull(); } @Test diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/MappedJwtClaimSetConverter.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/MappedJwtClaimSetConverter.java index 221c6d730c..d912581b7a 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/MappedJwtClaimSetConverter.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/MappedJwtClaimSetConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -52,18 +52,19 @@ public final class MappedJwtClaimSetConverter implements Converter> claimTypeConverters; - private final Converter, Map> delegate; - /** * Constructs a {@link MappedJwtClaimSetConverter} with the provided arguments * * This will completely replace any set of default converters. + * + * A converter that returns {@code null} removes the claim from the claim set. A + * converter that returns a non-{@code null} value adds or replaces that claim in the + * claim set. * @param claimTypeConverters The {@link Map} of converters to use */ public MappedJwtClaimSetConverter(Map> claimTypeConverters) { Assert.notNull(claimTypeConverters, "claimTypeConverters cannot be null"); this.claimTypeConverters = claimTypeConverters; - this.delegate = new ClaimTypeConverter(claimTypeConverters); } /** @@ -87,6 +88,10 @@ public final class MappedJwtClaimSetConverter implements Converter convert(Map claims) { Assert.notNull(claims, "claims cannot be null"); - Map mappedClaims = this.delegate.convert(claims); - mappedClaims = removeClaims(mappedClaims); - mappedClaims = addClaims(mappedClaims); + Map mappedClaims = new HashMap<>(claims); + for (Map.Entry> entry : this.claimTypeConverters.entrySet()) { + String claimName = entry.getKey(); + Converter converter = entry.getValue(); + if (converter != null) { + Object claim = claims.get(claimName); + Object mappedClaim = converter.convert(claim); + mappedClaims.compute(claimName, (key, value) -> mappedClaim); + } + } Instant issuedAt = (Instant) mappedClaims.get(JwtClaimNames.IAT); Instant expiresAt = (Instant) mappedClaims.get(JwtClaimNames.EXP); if (issuedAt == null && expiresAt != null) { @@ -154,24 +166,4 @@ public final class MappedJwtClaimSetConverter implements Converter removeClaims(Map claims) { - Map result = new HashMap<>(); - for (Map.Entry entry : claims.entrySet()) { - if (entry.getValue() != null) { - result.put(entry.getKey(), entry.getValue()); - } - } - return result; - } - - private Map addClaims(Map claims) { - Map result = new HashMap<>(claims); - for (Map.Entry> entry : this.claimTypeConverters.entrySet()) { - if (!claims.containsKey(entry.getKey()) && entry.getValue().convert(null) != null) { - result.put(entry.getKey(), entry.getValue().convert(null)); - } - } - return result; - } - } diff --git a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/MappedJwtClaimSetConverterTests.java b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/MappedJwtClaimSetConverterTests.java index 29a5a5b536..11d4b105ec 100644 --- a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/MappedJwtClaimSetConverterTests.java +++ b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/MappedJwtClaimSetConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License.