[java-oidc-common] branch main updated: JCOMOIDC-166 - Decoding of list valued claims fails
Codeberg
noreply at shibboleth.net
Tue Aug 25 12:59:46 UTC 2026
This is an automated email from the git hooks/post-receive script.
codeberg pushed a commit to branch main
in repository java-oidc-common.
View the commit online:
https://codeberg.org/Shibboleth/java-oidc-common/commit/d26e3acd09b58c56102d1c09a18ece4722e80884
The following commit(s) were added to refs/heads/main by this push:
new d26e3acd JCOMOIDC-166 - Decoding of list valued claims fails
d26e3acd is described below
commit d26e3acd09b58c56102d1c09a18ece4722e80884
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Tue Aug 25 13:59:36 2026 +0100
JCOMOIDC-166 - Decoding of list valued claims fails
- Added List to the supported types to decode
https://shibboleth.atlassian.net/browse/JCOMOIDC-166
---
.../impl/OIDCScopedStringAttributeTranscoder.java | 14 +++--
.../impl/OIDCStringAttributeTranscoder.java | 21 +++++--
.../OIDCScopedStringAttributeTranscoderTest.java | 33 +++++++++++
.../impl/OIDCStringAttributeTranscoderTest.java | 67 ++++++++++++++++++++++
4 files changed, 127 insertions(+), 8 deletions(-)
diff --git a/oidc-common-attribute-impl/src/main/java/net/shibboleth/oidc/attribute/transcoding/impl/OIDCScopedStringAttributeTranscoder.java b/oidc-common-attribute-impl/src/main/java/net/shibboleth/oidc/attribute/transcoding/impl/OIDCScopedStringAttributeTranscoder.java
index 18c6aad5..ecc30853 100644
--- a/oidc-common-attribute-impl/src/main/java/net/shibboleth/oidc/attribute/transcoding/impl/OIDCScopedStringAttributeTranscoder.java
+++ b/oidc-common-attribute-impl/src/main/java/net/shibboleth/oidc/attribute/transcoding/impl/OIDCScopedStringAttributeTranscoder.java
@@ -106,8 +106,7 @@ public class OIDCScopedStringAttributeTranscoder extends AbstractOIDCAttributeTr
@Nullable final ProfileRequestContext profileRequestContext, @Nonnull final Object input,
@Nonnull final TranscodingRule rule) throws AttributeDecodingException {
- if (input instanceof String) {
- final String stringValue = (String)input;
+ if (input instanceof final String stringValue) {
final String scopeDelimiter = rule.getOrDefault(PROP_SCOPE_DELIMITER, String.class, "@");
assert scopeDelimiter != null;
final int offset = stringValue.indexOf(scopeDelimiter);
@@ -119,9 +118,8 @@ public class OIDCScopedStringAttributeTranscoder extends AbstractOIDCAttributeTr
assert scope != null;
return CollectionSupport.listOf(ScopedStringAttributeValue.valueOf(stringValue.substring(0, offset),
scope));
- } else if (input instanceof JSONArray) {
+ } else if (input instanceof final JSONArray array) {
// Deal with array recursively
- final JSONArray array = (JSONArray)input;
final List<IdPAttributeValue> arrayValuesDecoded = new ArrayList<>();
for (final Object element : array) {
assert element != null;
@@ -129,6 +127,14 @@ public class OIDCScopedStringAttributeTranscoder extends AbstractOIDCAttributeTr
}
return arrayValuesDecoded;
+ } else if (input instanceof final List list){
+ // Deal with array recursively
+ final List<IdPAttributeValue> arrayValuesDecoded = new ArrayList<>();
+ for (final Object element : list) {
+ assert element != null;
+ arrayValuesDecoded.addAll(decodeValues(profileRequestContext, element, rule));
+ }
+ return arrayValuesDecoded;
} else {
log.trace("Could not convert values of type {} for the claim '{}' to a scoped string attribute using "
+ "transcoding rule '{} -> {}'",
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 8b34380c..4a1f7ac7 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
@@ -195,15 +195,13 @@ public class OIDCStringAttributeTranscoder extends AbstractOIDCAttributeTranscod
return CollectionSupport.listOf(StringAttributeValue.valueOf(Double.toString((Double)input)));
} else if (input instanceof Boolean && boolAsString) {
return CollectionSupport.listOf(StringAttributeValue.valueOf(Boolean.toString((Boolean)input)));
- } else if (input instanceof JSONArray) {
+ } else if (input instanceof final JSONArray array) {
final Boolean arrayAsString = rule.getOrDefault(PROP_ARRAY_AS_STRING, Boolean.class, false);
assert arrayAsString != null;
if (arrayAsString) {
// Serialize JSON Array to JSON string
return CollectionSupport.listOf(StringAttributeValue.valueOf(((JSONArray)input).toJSONString()));
} else {
- // Deal with array recursively
- final JSONArray array = (JSONArray) input;
final List<IdPAttributeValue> arrayValuesDecoded = new ArrayList<>();
for (final Object element : array) {
assert element != null;
@@ -212,7 +210,7 @@ public class OIDCStringAttributeTranscoder extends AbstractOIDCAttributeTranscod
return arrayValuesDecoded;
}
- } if (input instanceof JSONObject && asObject) {
+ } else if (input instanceof JSONObject && asObject) {
// Serialize JSONObject to a JSON string.
return CollectionSupport.listOf(StringAttributeValue.valueOf(((JSONObject)input).toJSONString()));
@@ -228,6 +226,21 @@ public class OIDCStringAttributeTranscoder extends AbstractOIDCAttributeTranscod
return CollectionSupport.listOf(StringAttributeValue.valueOf(
new JSONObject(mapWithStringKeys).toJSONString()));
+
+ } else if(input instanceof final List inputList) {
+ final Boolean arrayAsString = rule.getOrDefault(PROP_ARRAY_AS_STRING, Boolean.class, false);
+ assert arrayAsString != null;
+ if (arrayAsString) {
+ // Serialize JSON Array to JSON string, use same method as if JSONArray for consistent output
+ return CollectionSupport.listOf(StringAttributeValue.valueOf(JSONArray.toJSONString(inputList)));
+ } else {
+ final List<IdPAttributeValue> arrayValuesDecoded = new ArrayList<>();
+ for (final Object element : inputList) {
+ assert element != null;
+ arrayValuesDecoded.addAll(decodeValues(profileRequestContext, element, rule));
+ }
+ return arrayValuesDecoded;
+ }
} else {
log.trace("Could not convert values of type {} for the claim '{}' to a string attribute using "
+ "transcoding rule '{} -> {}'",
diff --git a/oidc-common-attribute-impl/src/test/java/net/shibboleth/oidc/attribute/transcoding/impl/OIDCScopedStringAttributeTranscoderTest.java b/oidc-common-attribute-impl/src/test/java/net/shibboleth/oidc/attribute/transcoding/impl/OIDCScopedStringAttributeTranscoderTest.java
index a790ffe1..11cde387 100644
--- a/oidc-common-attribute-impl/src/test/java/net/shibboleth/oidc/attribute/transcoding/impl/OIDCScopedStringAttributeTranscoderTest.java
+++ b/oidc-common-attribute-impl/src/test/java/net/shibboleth/oidc/attribute/transcoding/impl/OIDCScopedStringAttributeTranscoderTest.java
@@ -363,6 +363,39 @@ public class OIDCScopedStringAttributeTranscoderTest {
Assert.assertEquals(((ScopedStringAttributeValue)decodedAttribute.getValues().get(1)).getValue(), STRING_2);
}
+ // See JCOMOIDC-166
+ @Test
+ public void testDecodingStringArray_UsingArrayList()
+ throws ComponentInitializationException, AttributeDecodingException {
+
+ registry.setTranscoderRegistry(CollectionSupport.singletonList(new TranscodingRule(ruleset)));
+ registry.setApplicationContext(new MockApplicationContext());
+ registry.initialize();
+
+ // Map from oidc claim.name 'bar' to shib attribute id 'foo'.
+ final JSONObject inputAttribute = new JSONObject();
+ final List<String> values = new ArrayList<>();
+ values.add(STRING_1+ DELIMITER + SCOPE_1);
+ values.add(STRING_2+ DELIMITER + SCOPE_2);
+ inputAttribute.put(ATTR_NAME, values);
+
+ 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(), 2);
+ Assert.assertEquals(((ScopedStringAttributeValue)decodedAttribute.getValues().get(0)).getScope(), SCOPE_1);
+ Assert.assertEquals(((ScopedStringAttributeValue)decodedAttribute.getValues().get(0)).getValue(), STRING_1);
+ Assert.assertEquals(((ScopedStringAttributeValue)decodedAttribute.getValues().get(1)).getScope(), SCOPE_2);
+ Assert.assertEquals(((ScopedStringAttributeValue)decodedAttribute.getValues().get(1)).getValue(), STRING_2);
+ }
+
@Test
public void testDecodingComplexArray() throws ComponentInitializationException, AttributeDecodingException {
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 6049e12f..52aecf67 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
@@ -380,6 +380,73 @@ public class OIDCStringAttributeTranscoderTest {
Assert.assertEquals(decodedAttribute.getValues().get(1).getNativeValue(), "Second");
}
+ // See JCOMOIDC-166
+ @Test
+ public void testDecodingStringArray_UsingArrayList()
+ throws ComponentInitializationException, AttributeDecodingException {
+
+ assert ruleset != null;
+ registry.setTranscoderRegistry(CollectionSupport.singletonList(new TranscodingRule(ruleset)));
+ registry.setApplicationContext(new MockApplicationContext());
+ registry.initialize();
+
+ // Map from oidc claim.name 'bar' to shib attribute id 'foo'.
+ final JSONObject inputAttribute = new JSONObject();
+ final List<String> values = new ArrayList<>();
+ values.add("https://refeds.org/assurance");
+ values.add("https://refeds.org/assurance/IAP/low");
+ inputAttribute.put(ATTR_NAME, values);
+
+ 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(), 2);
+ Assert.assertEquals(decodedAttribute.getValues().get(0).getNativeValue(), "https://refeds.org/assurance");
+ Assert.assertEquals(decodedAttribute.getValues().get(1).getNativeValue(),
+ "https://refeds.org/assurance/IAP/low");
+ }
+
+ // See JCOMOIDC-166
+ @Test
+ public void testDecodingStringArrayAsJSONString_UsingArrayList()
+ throws ComponentInitializationException, AttributeDecodingException {
+
+ ruleset.put(OIDCStringAttributeTranscoder.PROP_ARRAY_AS_STRING, true);
+
+ assert ruleset != null;
+ registry.setTranscoderRegistry(CollectionSupport.singletonList(new TranscodingRule(ruleset)));
+ registry.setApplicationContext(new MockApplicationContext());
+ registry.initialize();
+
+ // Map from oidc claim.name 'bar' to shib attribute id 'foo'.
+ final JSONObject inputAttribute = new JSONObject();
+ final List<String> values = new ArrayList<>();
+ values.add("https://refeds.org/assurance");
+ values.add("https://refeds.org/assurance/IAP/low");
+ inputAttribute.put(ATTR_NAME, values);
+
+ 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.assertEquals(decodedAttribute.getValues().get(0).getNativeValue(),
+ "[\"https:\\/\\/refeds.org\\/assurance\",\"https:\\/\\/refeds.org\\/assurance\\/IAP\\/low\"]");
+ }
+
@Test
public void testDecodingStringArrayAsString() 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