[java-oidc-common] branch main updated: JCOMOIDC-103 - Add metadata-driven naming to attribute transcoders
Henri Mikkonen
henri.mikkonen at iki.fi
Thu Mar 14 08:37:58 UTC 2024
This is an automated email from the git hooks/post-receive script.
hjmikkon 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=6c2f28d0eb28f4725d8759fc3d1994190c5bb7b9
The following commit(s) were added to refs/heads/main by this push:
new 6c2f28d JCOMOIDC-103 - Add metadata-driven naming to attribute transcoders
6c2f28d is described below
commit 6c2f28d0eb28f4725d8759fc3d1994190c5bb7b9
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Thu Mar 14 10:37:38 2024 +0200
JCOMOIDC-103 - Add metadata-driven naming to attribute transcoders
https://shibboleth.atlassian.net/browse/JCOMOIDC-103
If the transcoder property flag 'oidc.nameFromSamlMetadata' is set to true,
then the OIDC claim name can be set via SAML metadata tag
'http://shibboleth.net/ns/attributes/naming/oidc'. The logic for the value
is '<attributeId> <claimName>', so for instance 'mail customEmailName'.
The AbstractOIDCAttributeTranscoder contains one variable and two methods
copied from IdP 5.1's AbstractAttributeTranscoder for keeping compatibility
with IdP 5.0. TODO-tags were added as a reminder of that.
---
.../AbstractOIDCAttributeTranscoder.java | 115 +++++++++++++++++++--
.../transcoding/OIDCAttributeTranscoder.java | 13 +++
2 files changed, 119 insertions(+), 9 deletions(-)
diff --git a/oidc-common-attribute-api/src/main/java/net/shibboleth/oidc/attribute/transcoding/AbstractOIDCAttributeTranscoder.java b/oidc-common-attribute-api/src/main/java/net/shibboleth/oidc/attribute/transcoding/AbstractOIDCAttributeTranscoder.java
index b539319..8f4cf3a 100644
--- a/oidc-common-attribute-api/src/main/java/net/shibboleth/oidc/attribute/transcoding/AbstractOIDCAttributeTranscoder.java
+++ b/oidc-common-attribute-api/src/main/java/net/shibboleth/oidc/attribute/transcoding/AbstractOIDCAttributeTranscoder.java
@@ -40,6 +40,7 @@ import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
import net.shibboleth.shared.collection.CollectionSupport;
import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.primitive.StringSupport;
/**
* Abstract class for OIDC attribute encoders.
@@ -50,12 +51,31 @@ public abstract class AbstractOIDCAttributeTranscoder
/** Class logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(AbstractOIDCAttributeTranscoder.class);
+ /** Strategy to lookup naming overrides in metadata. */
+ //TODO: The variable exists in AbstractAttributeTranscoder since 5.1, but we replicate it for 5.0 compatibility
+ @Nullable private Function<ProfileRequestContext,Set<String>> nameFromMetadataLookupStrategy;
+
/** {@inheritDoc} */
@Override
@Nonnull public Class<JSONObject> getEncodedType() {
return JSONObject.class;
}
+ /**
+ * Sets lookup strategy for obtaining tag-based naming overrides from metadata.
+ *
+ * @param strategy lookup strategy
+ *
+ * @since 3.1.0
+ */
+ //TODO: The method exists in AbstractAttributeTranscoder since 5.1, but we replicate it for 5.0 compatibility
+ public void setNameFromMetadataLookupStrategy(
+ @Nullable final Function<ProfileRequestContext,Set<String>> strategy) {
+ checkSetterPreconditions();
+
+ nameFromMetadataLookupStrategy = strategy;
+ }
+
/** {@inheritDoc} */
@Override
@Nullable public String getEncodedName(@Nonnull final TranscodingRule rule) {
@@ -67,7 +87,7 @@ public abstract class AbstractOIDCAttributeTranscoder
}
return null;
}
-
+
/** {@inheritDoc} */
@Override
@Nullable public JSONObject doEncode(@Nullable final ProfileRequestContext profileRequestContext,
@@ -108,18 +128,58 @@ public abstract class AbstractOIDCAttributeTranscoder
if (claimValues == null) {
throw new AttributeEncodingException("Unable to build OIDC claim with no value(s)");
}
-
- final String name = rule.getOrDefault(PROP_NAME, String.class, attribute != null ? attribute.getId() : null);
- if (Strings.isNullOrEmpty(name)) {
- throw new AttributeEncodingException("Required transcoder property '" + PROP_NAME + "' not found");
- }
-
+
+ final String name = getEncodedName(profileRequestContext, attribute, rule);
final JSONObject claim = new JSONObject();
claim.put(name, claimValues);
return claim;
}
+ /**
+ * Get the encoded name for the attribute via SAML metadata (if enabled) or rule's name property.
+ *
+ * @param profileRequestContext current profile request context
+ * @param attribute the attribute being encoded
+ * @param rule properties to control encoding
+ *
+ * @return the name of the OIDC claim
+ *
+ * @throws AttributeEncodingException if there's a problem constructing the name
+ */
+ protected String getEncodedName(@Nullable final ProfileRequestContext profileRequestContext,
+ @Nullable final IdPAttribute attribute, @Nonnull final TranscodingRule rule)
+ throws AttributeEncodingException {
+ final Boolean useMetadata = rule.getOrDefault(PROP_NAME_FROM_METADATA, Boolean.class, false);
+ if (useMetadata != null && useMetadata) {
+ final String id = attribute != null ? attribute.getId() :
+ rule.get(AttributeTranscoderRegistry.PROP_ID, String.class);
+ if (id == null) {
+ log.warn("Rule specified {} but no attribute ID available", PROP_NAME_FROM_METADATA);
+ } else {
+ final String tagValue = getNameFromMetadata(profileRequestContext, id);
+ if (tagValue != null) {
+ final int lastSpace = tagValue.lastIndexOf(' ');
+ final String name;
+ if (lastSpace < 0) {
+ name = StringSupport.trimOrNull(tagValue);
+ } else {
+ name = StringSupport.trimOrNull(tagValue.substring(0, lastSpace));
+ }
+ if (name != null) {
+ return name;
+ }
+ log.warn("Metadata tag {}, value {}, was not in the expected form", METADATA_TAG_NAME, tagValue);
+ }
+ }
+ }
+ final String name = rule.getOrDefault(PROP_NAME, String.class, attribute != null ? attribute.getId() : null);
+ if (Strings.isNullOrEmpty(name)) {
+ throw new AttributeEncodingException("Required transcoder property '" + PROP_NAME + "' not found");
+ }
+ return name;
+ }
+
/**
* Performs encoding of {@link IdPAttribute}'s values based on rule into a claim value.
*
@@ -216,8 +276,45 @@ public abstract class AbstractOIDCAttributeTranscoder
@Nullable final ProfileRequestContext profileRequestContext, @Nonnull final Object input,
@Nonnull final TranscodingRule rule) throws AttributeDecodingException;
-
- /**
+
+ /**
+ * If enabled, search metadata for a tag value prefixed by the input attribute ID followed by
+ * a space character.
+ *
+ * <p>The remaining portion of the value will be interpreted in a protocol-specific way.</p>
+ *
+ * @param profileRequestContext profile request context
+ * @param attributeId attribute ID
+ *
+ * @return the first matching tag value from the installed lookup function
+ *
+ * @since 3.1.0
+ */
+ //TODO: The method exists in AbstractAttributeTranscoder since 5.1, but we replicate it for 5.0 compatibility
+ @Nullable protected String getNameFromMetadata(@Nullable final ProfileRequestContext profileRequestContext,
+ @Nonnull final String attributeId) {
+
+ if (nameFromMetadataLookupStrategy != null) {
+ final Set<String> tagValues = nameFromMetadataLookupStrategy.apply(profileRequestContext);
+ if (tagValues != null) {
+ for (final String tagValue : tagValues) {
+ if (tagValue != null && tagValue.startsWith(attributeId + ' ')) {
+ final String ret = tagValue.substring(attributeId.length() + 1);
+ if (!ret.isEmpty()) {
+ return ret;
+ }
+ }
+ }
+ log.debug("No applicable tag value found for metadata-driven naming for {}", attributeId);
+ } else {
+ log.debug("No tag values found for metadata-driven naming for {}", attributeId);
+ }
+ }
+
+ return null;
+ }
+
+ /**
* A function to produce a "canonical" name for an OIDC claim for transcoding rules.
*/
public static class NamingFunction implements Function<JSONObject,String> {
diff --git a/oidc-common-attribute-api/src/main/java/net/shibboleth/oidc/attribute/transcoding/OIDCAttributeTranscoder.java b/oidc-common-attribute-api/src/main/java/net/shibboleth/oidc/attribute/transcoding/OIDCAttributeTranscoder.java
index 0712c2b..00b816b 100644
--- a/oidc-common-attribute-api/src/main/java/net/shibboleth/oidc/attribute/transcoding/OIDCAttributeTranscoder.java
+++ b/oidc-common-attribute-api/src/main/java/net/shibboleth/oidc/attribute/transcoding/OIDCAttributeTranscoder.java
@@ -49,4 +49,17 @@ public interface OIDCAttributeTranscoder extends AttributeTranscoder<JSONObject>
/** Whether to decode a JSON Array into a serialized JSON string. */
@Nonnull @NotEmpty static final String PROP_ARRAY_AS_STRING = "oidc.arrayAsString";
+ /**
+ * Flag to signal use of metadata to override name to encode.
+ *
+ * @since 3.1.0
+ */
+ @Nonnull @NotEmpty static final String PROP_NAME_FROM_METADATA = "oidc.nameFromSamlMetadata";
+
+ /**
+ * Name of metadata tag/attribute to check for in the event that {@link #PROP_NAME_FROM_METADATA} is used.
+ *
+ * @since 3.1.0
+ */
+ @Nonnull @NotEmpty static final String METADATA_TAG_NAME = "http://shibboleth.net/ns/attributes/naming/oidc";
}
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list