[java-oidc-common] branch main updated: JCOMOIDC-127 - Transcoding of object type of claim fails

Phil Smart philip.smart at jisc.ac.uk
Thu Apr 17 10:54:51 UTC 2025


This is an automated email from the git hooks/post-receive script.

philsmart pushed a commit to branch main
in repository java-oidc-common.

View the commit online:
http://git.shibboleth.net/view/?p=java-oidc-common.git;a=commit;h=126b9eafb60e05d09c0583434dc6f390a10fcf15

The following commit(s) were added to refs/heads/main by this push:
     new 126b9ea  JCOMOIDC-127 - Transcoding of object type of claim fails
126b9ea is described below

commit 126b9eafb60e05d09c0583434dc6f390a10fcf15
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Thu Apr 17 11:54:49 2025 +0100

    JCOMOIDC-127 - Transcoding of object type of claim fails
    
     - Added a conditional statement to the decode method that serialises
    any Map type into a JSON string.
    
    https://shibboleth.atlassian.net/browse/JCOMOIDC-127
---
 .../impl/OIDCStringAttributeTranscoder.java        | 25 ++++++++++----
 .../impl/OIDCStringAttributeTranscoderTest.java    | 39 ++++++++++++++++++++++
 2 files changed, 58 insertions(+), 6 deletions(-)

diff --git a/oidc-common-attribute-impl/src/main/java/net/shibboleth/oidc/attribute/transcoding/impl/OIDCStringAttributeTranscoder.java b/oidc-common-attribute-impl/src/main/java/net/shibboleth/oidc/attribute/transcoding/impl/OIDCStringAttributeTranscoder.java
index 268cc8a..8e0e829 100644
--- a/oidc-common-attribute-impl/src/main/java/net/shibboleth/oidc/attribute/transcoding/impl/OIDCStringAttributeTranscoder.java
+++ b/oidc-common-attribute-impl/src/main/java/net/shibboleth/oidc/attribute/transcoding/impl/OIDCStringAttributeTranscoder.java
@@ -15,7 +15,9 @@
 package net.shibboleth.oidc.attribute.transcoding.impl;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
@@ -68,8 +70,8 @@ import net.shibboleth.shared.primitive.LoggerFactory;
  * <li>If a JSON Array and PROP_ARRAY_AS_STRING is false, attempt to recursively convert elements of the array
  * to string attribute values using the same set of rules. If any element fails to convert it will be excluded
  * from the result.</li>
- * <li>If a JSON Object and PROP_ASOBJECT is true, convert the object to a string by serializing into JSON. Else,
- * return an empty values list.</li>
+ * <li>If a JSON Object or a generic Map and PROP_ASOBJECT is true, convert the object to a string by serializing into 
+ * JSON. Else, return an empty values list.</li>
  * <li>For any other unknown type, return an empty values list.</li>
  * </ul>
  */
@@ -175,8 +177,7 @@ public class OIDCStringAttributeTranscoder extends AbstractOIDCAttributeTranscod
         // Input could be any JSON data type e.g. String, Number, JSONObject, Array, Boolean.
              
         if (input instanceof String) {            
-            return CollectionSupport.listOf(StringAttributeValue.valueOf((String)input));  
-            
+            return CollectionSupport.listOf(StringAttributeValue.valueOf((String)input));   
         }
         
         final Boolean numAsString = rule.getOrDefault(PROP_NUMBER_AS_STRING, Boolean.class, false);
@@ -211,12 +212,24 @@ public class OIDCStringAttributeTranscoder extends AbstractOIDCAttributeTranscod
                 return arrayValuesDecoded;  
             }
             
-        } else if (input instanceof JSONObject && asObject) {
+        } if (input instanceof JSONObject && asObject) {
             // Serialize JSONObject to a JSON string.
             return CollectionSupport.listOf(StringAttributeValue.valueOf(((JSONObject)input).toJSONString()));
             
+        } else if (input instanceof final Map<?,?> mapInput && asObject) { 
+            final Map<String, Object> mapWithStringKeys = new HashMap<>();
+            
+            // Only convert values which have String keys.
+            for (final Map.Entry<?, ?> entry : mapInput.entrySet()) {
+                if (entry.getKey() instanceof String) {
+                    mapWithStringKeys.put((String) entry.getKey(), entry.getValue());
+                }
+            }
+            
+            return CollectionSupport.listOf(StringAttributeValue.valueOf(
+                    new JSONObject(mapWithStringKeys).toJSONString()));
         } else {
-            log.trace("Could not convert values of type {} for the claim '{}' to a string attribute using "
+            log.warn("Could not convert values of type {} for the claim '{}' to a string attribute using "
                     + "transcoding rule '{} -> {}'",
                     input.getClass().getName(), input, rule.getOrDefault(PROP_NAME, String.class, "unknown"), 
                     rule.getOrDefault(AttributeTranscoderRegistry.PROP_ID, String.class, "unknown"));
diff --git a/oidc-common-attribute-impl/src/test/java/net/shibboleth/oidc/attribute/transcoding/impl/OIDCStringAttributeTranscoderTest.java b/oidc-common-attribute-impl/src/test/java/net/shibboleth/oidc/attribute/transcoding/impl/OIDCStringAttributeTranscoderTest.java
index f7ccb07..6049e12 100644
--- a/oidc-common-attribute-impl/src/test/java/net/shibboleth/oidc/attribute/transcoding/impl/OIDCStringAttributeTranscoderTest.java
+++ b/oidc-common-attribute-impl/src/test/java/net/shibboleth/oidc/attribute/transcoding/impl/OIDCStringAttributeTranscoderTest.java
@@ -25,6 +25,7 @@ import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import com.nimbusds.jose.shaded.gson.internal.LinkedTreeMap;
 import com.nimbusds.openid.connect.sdk.claims.ClaimsSetRequest;
 
 import net.minidev.json.JSONArray;
@@ -690,6 +691,44 @@ public class OIDCStringAttributeTranscoderTest {
                 .getNativeValue(), "{\"name\":\"John\",\"age\":\"30\"}");
     }
     
+    /* Nimbus delivers some claims as LinkedTreeMap, See https://shibboleth.atlassian.net/browse/JCOMOIDC-127 */
+    @Test
+    public void testDecodingLinkedTreeMap() throws ComponentInitializationException, AttributeDecodingException {
+        
+        ruleset.put(OIDCStringAttributeTranscoder.PROP_ASOBJECT, true);
+        
+        registry.setTranscoderRegistry(CollectionSupport.singletonList(new TranscodingRule(ruleset)));
+        registry.setApplicationContext(new MockApplicationContext());        
+        registry.initialize();        
+       
+        final JSONObject inputAttribute = new JSONObject(); 
+        
+        final LinkedTreeMap<String, String> linkedTree = new LinkedTreeMap<>();
+        
+        linkedTree.put("address", "234 Hollywood Blvd.");
+        linkedTree.put("country", "US");
+        linkedTree.put("locality", "Los Angeles");
+        linkedTree.put("CA", "90210");
+        
+        inputAttribute.put("bar", linkedTree);
+
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute);
+        Assert.assertEquals(rulesets.size(), 1);
+        final TranscodingRule tr = rulesets.iterator().next();
+        assert tr != null;
+
+        final IdPAttribute decodedAttribute = TranscoderSupport.<JSONObject>getTranscoder(tr)
+                .decode(null, inputAttribute, tr);
+
+        assert decodedAttribute != null;
+        Assert.assertEquals(decodedAttribute.getId(), ATTR_ID);
+        Assert.assertEquals(decodedAttribute.getValues().size(), 1);
+        Assert.assertNotNull(decodedAttribute.getValues().get(0).getNativeValue());
+        Assert.assertEquals(decodedAttribute.getValues().get(0)
+                .getNativeValue(), "{\"locality\":\"Los Angeles\",\"country\":\"US\",\"address\":"
+                        + "\"234 Hollywood Blvd.\",\"CA\":\"90210\"}");
+    }
+    
     @Test
     public void testDecodingJSONObjectDisabledByRule() throws ComponentInitializationException, AttributeDecodingException {
         

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list