[java-shib-attribute] branch main updated: IDP-2057 - Support transcoders that derive SAML naming from metadata

Scott Cantor cantor.2 at osu.edu
Tue Dec 12 14:07:33 UTC 2023


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

scantor pushed a commit to branch main
in repository java-shib-attribute.

View the commit online:
http://git.shibboleth.net/view/?p=java-shib-attribute.git;a=commit;h=ecb8c068e19e409a3f3a2c82cb9cfbf2c6280454

The following commit(s) were added to refs/heads/main by this push:
     new ecb8c068e IDP-2057 - Support transcoders that derive SAML naming from metadata
ecb8c068e is described below

commit ecb8c068e19e409a3f3a2c82cb9cfbf2c6280454
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Dec 12 09:07:30 2023 -0500

    IDP-2057 - Support transcoders that derive SAML naming from metadata
    
    https://shibboleth.atlassian.net/browse/IDP-2057
    
    Add support for metadata-driven naming to SAML transcoders.
    Adjust registry to accomodate rules with no target name.
---
 .../transcoding/AbstractAttributeTranscoder.java   | 59 +++++++++++++-
 .../impl/AttributeTranscoderRegistryImpl.java      | 95 ++++++++++++----------
 .../AbstractSAML1AttributeTranscoder.java          | 54 ++++++++++--
 .../AbstractSAML2AttributeTranscoder.java          | 61 ++++++++++++--
 .../transcoding/SAML1AttributeTranscoder.java      | 14 ++++
 .../transcoding/SAML2AttributeTranscoder.java      | 14 ++++
 6 files changed, 236 insertions(+), 61 deletions(-)

diff --git a/shib-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AbstractAttributeTranscoder.java b/shib-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AbstractAttributeTranscoder.java
index d3dde9fb1..dae1b01c1 100644
--- a/shib-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AbstractAttributeTranscoder.java
+++ b/shib-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AbstractAttributeTranscoder.java
@@ -14,6 +14,8 @@
 
 package net.shibboleth.idp.attribute.transcoding;
 
+import java.util.Set;
+import java.util.function.Function;
 import java.util.function.Predicate;
 
 import javax.annotation.Nonnull;
@@ -44,6 +46,9 @@ public abstract class AbstractAttributeTranscoder<T> extends AbstractInitializab
     /** Condition for use of this transcoder. */
     @Nonnull private Predicate<ProfileRequestContext> activationCondition;
     
+    /** Strategy to lookup naming overrides in metadata. */
+    @Nullable private Function<ProfileRequestContext,Set<String>> nameFromMetadataLookupStrategy;
+    
     /** Constructor. */
     public AbstractAttributeTranscoder() {
         activationCondition = PredicateSupport.alwaysTrue();
@@ -59,6 +64,20 @@ public abstract class AbstractAttributeTranscoder<T> extends AbstractInitializab
         
         activationCondition = Constraint.isNotNull(condition, "Activation condition cannot be null");
     }
+    
+    /**
+     * Sets lookup strategy for obtaining tag-based naming overrides from metadata.
+     * 
+     * @param strategy  lookup strategy
+     * 
+     * @since 5.1.0
+     */
+    public void setNameFromMetadataLookupStrategy(
+            @Nullable final Function<ProfileRequestContext,Set<String>> strategy) {
+        checkSetterPreconditions();
+        
+        nameFromMetadataLookupStrategy = strategy;
+    }
 
     /** {@inheritDoc} */
     @Nullable public T encode(@Nullable final ProfileRequestContext profileRequestContext,
@@ -89,6 +108,41 @@ public abstract class AbstractAttributeTranscoder<T> extends AbstractInitializab
         return attribute;
     }
     
+    /**
+     * 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 5.1.0
+     */
+    @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;
+    }
     
     /**
      * Encode the supplied attribute into a protocol specific representation.
@@ -135,7 +189,7 @@ public abstract class AbstractAttributeTranscoder<T> extends AbstractInitializab
             @Nonnull final TranscodingRule rule) {
         
         if (!activationCondition.test(profileRequestContext)) {
-            log.debug("Transcoder inactive");
+            log.debug("Transcoder type {} inactive", getClass().getName());
             return false;
         }
 
@@ -144,7 +198,8 @@ public abstract class AbstractAttributeTranscoder<T> extends AbstractInitializab
                 rule.get(AttributeTranscoderRegistry.PROP_CONDITION, Predicate.class);
         if (condition != null) {
             if (!condition.test(profileRequestContext)) {
-                log.debug("Transcoder inactive");
+                log.debug("Transcoder rule for {} inactive",
+                        rule.get(AttributeTranscoderRegistry.PROP_ID, String.class));
                 return false;
             }
         }
diff --git a/shib-attribute-impl/src/main/java/net/shibboleth/idp/attribute/transcoding/impl/AttributeTranscoderRegistryImpl.java b/shib-attribute-impl/src/main/java/net/shibboleth/idp/attribute/transcoding/impl/AttributeTranscoderRegistryImpl.java
index 161a73697..57e269551 100644
--- a/shib-attribute-impl/src/main/java/net/shibboleth/idp/attribute/transcoding/impl/AttributeTranscoderRegistryImpl.java
+++ b/shib-attribute-impl/src/main/java/net/shibboleth/idp/attribute/transcoding/impl/AttributeTranscoderRegistryImpl.java
@@ -319,60 +319,67 @@ public class AttributeTranscoderRegistryImpl extends AbstractIdentifiableInitial
 
         final Class<?> type = transcoder.getEncodedType();
         final String targetName = transcoder.getEncodedName(copy);
-        if (targetName != null) {
-            
-            Boolean encoder = copy.getOrDefault(PROP_ENCODER, Boolean.class, true);
-            if (encoder == null) {
-                encoder = true;
-            }
-            Boolean decoder = copy.getOrDefault(PROP_DECODER, Boolean.class, true);
-            if (decoder == null) {
-                decoder = true;
-            }
-            if (!encoder && !decoder) {
-                log.warn("Transcoding rule for {} and type {} was disabled in both directions, ignoring",
-                        id, type.getName());
-                return;
-            }
             
+        Boolean encoder = copy.getOrDefault(PROP_ENCODER, Boolean.class, true);
+        if (encoder == null) {
+            encoder = true;
+        }
+        Boolean decoder = copy.getOrDefault(PROP_DECODER, Boolean.class, true);
+        if (decoder == null) {
+            decoder = true;
+        }
+
+        if (decoder && targetName == null) {
+            log.warn("Transcoding rule for {} and type {} did not produce a decodable target name, disabling decoding",
+                    id, type.getName());
+            decoder = false;
+        }
+        
+        if (!encoder && !decoder) {
+            log.warn("Transcoding rule for {} and type {} was disabled in both directions, ignoring",
+                    id, type.getName());
+            return;
+        }
+        
+        if (targetName != null) {
             log.debug("Attribute mapping: {} {}-{} {} via {}", id, decoder ? "<" : "", encoder ? ">" : "", targetName,
                     transcoder.getClass().getSimpleName());
-            
-            // Install mapping back to IdPAttribute's trimmed name.
-            copy.getMap().put(PROP_ID, id);
+        } else {
+            log.debug("Attribute mapping: {} {}-{} (metadata-driven naming only) via {}", id, decoder ? "<" : "",
+                    encoder ? ">" : "", transcoder.getClass().getSimpleName());
+        }
+        
+        // Install mapping back to IdPAttribute's trimmed name.
+        copy.getMap().put(PROP_ID, id);
 
-            if (encoder) {
-                Multimap<Class<?>,TranscodingRule> rulesetsForIdPName = transcodingRegistry.get(id);
-                if (rulesetsForIdPName == null) {
-                    rulesetsForIdPName = ArrayListMultimap.create();
-                    transcodingRegistry.put(id, rulesetsForIdPName);
-                }
-                rulesetsForIdPName.put(type, copy);
+        if (encoder) {
+            Multimap<Class<?>,TranscodingRule> rulesetsForIdPName = transcodingRegistry.get(id);
+            if (rulesetsForIdPName == null) {
+                rulesetsForIdPName = ArrayListMultimap.create();
+                transcodingRegistry.put(id, rulesetsForIdPName);
             }
+            rulesetsForIdPName.put(type, copy);
+        }
             
-            if (decoder) {
-                Multimap<Class<?>,TranscodingRule> rulesetsForEncodedName = transcodingRegistry.get(targetName);
-                if (rulesetsForEncodedName == null) {
-                    rulesetsForEncodedName = ArrayListMultimap.create();
-                    transcodingRegistry.put(targetName, rulesetsForEncodedName);
-                }
-                rulesetsForEncodedName.put(type, copy);
+        if (targetName != null && decoder) {
+            Multimap<Class<?>,TranscodingRule> rulesetsForEncodedName = transcodingRegistry.get(targetName);
+            if (rulesetsForEncodedName == null) {
+                rulesetsForEncodedName = ArrayListMultimap.create();
+                transcodingRegistry.put(targetName, rulesetsForEncodedName);
             }
+            rulesetsForEncodedName.put(type, copy);
+        }
             
-            if (displayNameRegistry.containsKey(id)) {
-                displayNameRegistry.get(id).putAll(copy.getDisplayNames());
-            } else {
-                displayNameRegistry.put(id, new HashMap<>(copy.getDisplayNames()));
-            }
+        if (displayNameRegistry.containsKey(id)) {
+            displayNameRegistry.get(id).putAll(copy.getDisplayNames());
+        } else {
+            displayNameRegistry.put(id, new HashMap<>(copy.getDisplayNames()));
+        }
 
-            if (descriptionRegistry.containsKey(id)) {
-                descriptionRegistry.get(id).putAll(copy.getDescriptions());
-            } else {
-                descriptionRegistry.put(id, new HashMap<>(copy.getDescriptions()));
-            }
-            
+        if (descriptionRegistry.containsKey(id)) {
+            descriptionRegistry.get(id).putAll(copy.getDescriptions());
         } else {
-            log.warn("Transcoding rule for {} and type {} did not produce an encoded name", id, type.getName());
+            descriptionRegistry.put(id, new HashMap<>(copy.getDescriptions()));
         }
     }
 // Checkstyle: CyclomaticComplexity ON
diff --git a/shib-saml-attribute-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAML1AttributeTranscoder.java b/shib-saml-attribute-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAML1AttributeTranscoder.java
index 9872e1934..c763f152e 100644
--- a/shib-saml-attribute-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAML1AttributeTranscoder.java
+++ b/shib-saml-attribute-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAML1AttributeTranscoder.java
@@ -40,6 +40,7 @@ import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.saml.xml.SAMLConstants;
 import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.primitive.StringSupport;
 
 /**
  * Base class for transcoders that operate on a SAML 1 {@link Attribute} or {@link AttributeDesignator}.
@@ -97,11 +98,6 @@ public abstract class AbstractSAML1AttributeTranscoder<EncodedType extends IdPAt
             throw new AttributeEncodingException("Failed to encode any values for attribute " + attribute.getId());
         }
 
-        final String name = rule.get(PROP_NAME, String.class);
-        if (Strings.isNullOrEmpty(name)) {
-            throw new AttributeEncodingException("Required transcoder property '" + PROP_NAME + "' not found");
-        }
-
         final AttributeDesignator samlAttribute;
         
         if (to.equals(Attribute.class)) {
@@ -120,11 +116,55 @@ public abstract class AbstractSAML1AttributeTranscoder<EncodedType extends IdPAt
             throw new AttributeEncodingException("Unsupported target object type: " + to.getName());
         }
 
+        encodeName(profileRequestContext, attribute, samlAttribute, rule);
+        
+        return samlAttribute;
+    }
+    
+    protected void encodeName(@Nullable final ProfileRequestContext profileRequestContext,
+            @Nullable final IdPAttribute attribute, @Nonnull final AttributeDesignator samlAttribute,
+            @Nonnull final TranscodingRule rule) throws AttributeEncodingException {
+        
+        // Use metadata tag to derive name of Attribute?
+        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;
+                    final String namespace;
+                    if (lastSpace < 0) {
+                        name = StringSupport.trimOrNull(tagValue);
+                        namespace = null;
+                    } else {
+                        name = StringSupport.trimOrNull(tagValue.substring(0, lastSpace));
+                        namespace = StringSupport.trimOrNull(tagValue.substring(lastSpace));
+                    }
+                    if (name != null) {
+                        samlAttribute.setAttributeName(name);
+                        samlAttribute.setAttributeNamespace(namespace);
+                        log.debug("Encoding IdPAttribute {} via metadata tag as Name {}, Namespace {}", id,
+                                name, namespace);
+                        return;
+                    }
+                    log.warn("Metadata tag {}, value {}, was not in the expected form", METADATA_TAG_NAME, tagValue);
+                }
+            }
+        }
+        
+        final String name = rule.get(PROP_NAME, String.class);
+        if (Strings.isNullOrEmpty(name)) {
+            throw new AttributeEncodingException("Required transcoder property '" + PROP_NAME + "' not found");
+        }
+        
         samlAttribute.setAttributeName(name);
         samlAttribute.setAttributeNamespace(
                 rule.getOrDefault(PROP_NAMESPACE, String.class, SAMLConstants.SAML1_ATTR_NAMESPACE_URI));
-        
-        return samlAttribute;
     }
     
     /** {@inheritDoc} */
diff --git a/shib-saml-attribute-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAML2AttributeTranscoder.java b/shib-saml-attribute-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAML2AttributeTranscoder.java
index ad0778bf3..141eff042 100644
--- a/shib-saml-attribute-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAML2AttributeTranscoder.java
+++ b/shib-saml-attribute-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAML2AttributeTranscoder.java
@@ -26,6 +26,7 @@ import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.saml.common.SAMLObjectBuilder;
 import org.opensaml.saml.saml2.core.Attribute;
 import org.opensaml.saml.saml2.metadata.RequestedAttribute;
+import org.slf4j.Logger;
 
 import com.google.common.base.Strings;
 
@@ -37,6 +38,8 @@ import net.shibboleth.idp.attribute.IdPRequestedAttribute;
 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;
 
 /**
  * Base class for transcoders that operate on a SAML 2 {@link Attribute} or {@link RequestedAttribute}.
@@ -46,6 +49,9 @@ import net.shibboleth.shared.collection.CollectionSupport;
 public abstract class AbstractSAML2AttributeTranscoder<EncodedType extends IdPAttributeValue> extends
         AbstractSAMLAttributeTranscoder<Attribute,EncodedType> implements SAML2AttributeTranscoder<EncodedType> {
     
+    /** Class logger. */
+    @Nonnull private final Logger log = LoggerFactory.getLogger(AbstractSAML2AttributeTranscoder.class);
+    
     /** Builder used to construct {@link Attribute} objects. */
     @Nonnull private final SAMLObjectBuilder<Attribute> attributeBuilder;
 
@@ -69,7 +75,6 @@ public abstract class AbstractSAML2AttributeTranscoder<EncodedType extends IdPAt
     
     /** {@inheritDoc} */
     @Nullable public String getEncodedName(@Nonnull final TranscodingRule rule) {
-        
         try {
             // SAML 2 naming should be based on only what needs to be available from the properties alone.
             return new NamingFunction().apply(buildAttribute(null, null, Attribute.class, rule,
@@ -90,11 +95,6 @@ public abstract class AbstractSAML2AttributeTranscoder<EncodedType extends IdPAt
             throw new AttributeEncodingException("Failed to encode any values for attribute " + attribute.getId());
         }
         
-        final String name = rule.get(PROP_NAME, String.class);
-        if (Strings.isNullOrEmpty(name)) {
-            throw new AttributeEncodingException("Required transcoder property '" + PROP_NAME + "' not found");
-        }
-
         final Attribute samlAttribute;
         
         if (to.equals(Attribute.class)) {
@@ -108,8 +108,8 @@ public abstract class AbstractSAML2AttributeTranscoder<EncodedType extends IdPAt
             throw new AttributeEncodingException("Unsupported target object type: " + to.getName());
         }
 
-        samlAttribute.setName(name);
-        samlAttribute.setNameFormat(rule.getOrDefault(PROP_NAME_FORMAT, String.class, Attribute.URI_REFERENCE));
+        encodeName(profileRequestContext, attribute, samlAttribute, rule);
+        
         samlAttribute.getAttributeValues().addAll(attributeValues);
         
         final String friendlyName = rule.getOrDefault(PROP_FRIENDLY_NAME, String.class,
@@ -121,6 +121,51 @@ public abstract class AbstractSAML2AttributeTranscoder<EncodedType extends IdPAt
         return samlAttribute;
     }
     
+    protected void encodeName(@Nullable final ProfileRequestContext profileRequestContext,
+            @Nullable final IdPAttribute attribute, @Nonnull final Attribute samlAttribute,
+            @Nonnull final TranscodingRule rule) throws AttributeEncodingException {
+        
+        // Use metadata tag to derive name of Attribute?
+        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;
+                    final String nameFormat;
+                    if (lastSpace < 0) {
+                        name = StringSupport.trimOrNull(tagValue);
+                        nameFormat = null;
+                    } else {
+                        name = StringSupport.trimOrNull(tagValue.substring(0, lastSpace));
+                        nameFormat = StringSupport.trimOrNull(tagValue.substring(lastSpace));
+                    }
+                    if (name != null) {
+                        samlAttribute.setName(name);
+                        samlAttribute.setNameFormat(nameFormat);
+                        log.debug("Encoding IdPAttribute {} via metadata tag as Name {}, NameFormat {}", id,
+                                name, nameFormat);
+                        return;
+                    }
+                    log.warn("Metadata tag {}, value {}, was not in the expected form", METADATA_TAG_NAME, tagValue);
+                }
+            }
+        }
+        
+        final String name = rule.get(PROP_NAME, String.class);
+        if (Strings.isNullOrEmpty(name)) {
+            throw new AttributeEncodingException("Required transcoder property '" + PROP_NAME + "' not found");
+        }
+        
+        samlAttribute.setName(name);
+        samlAttribute.setNameFormat(rule.getOrDefault(PROP_NAME_FORMAT, String.class, Attribute.URI_REFERENCE));
+    }
+    
     /** {@inheritDoc} */
     @Override
     @Nonnull protected IdPAttribute buildIdPAttribute(
diff --git a/shib-saml-attribute-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/SAML1AttributeTranscoder.java b/shib-saml-attribute-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/SAML1AttributeTranscoder.java
index 26430952d..cbdb5a1b4 100644
--- a/shib-saml-attribute-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/SAML1AttributeTranscoder.java
+++ b/shib-saml-attribute-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/SAML1AttributeTranscoder.java
@@ -40,4 +40,18 @@ public interface SAML1AttributeTranscoder<EncodedType extends IdPAttributeValue>
     /** The namespace of the attribute name. */
     @Nonnull @NotEmpty static final String PROP_NAMESPACE = "saml1.namespace";
 
+    /**
+     * Flag to signal use of metadata to override name to encode.
+     * 
+     * @since 5.1.0
+     */
+    @Nonnull @NotEmpty static final String PROP_NAME_FROM_METADATA = "saml1.nameFromMetadata";
+
+    /**
+     * Name of metadata tag/attribute to check for in the event that {@link #PROP_NAME_FROM_METADATA} is used.
+     * 
+     * @since 5.1.0
+     */
+    @Nonnull @NotEmpty static final String METADATA_TAG_NAME = "http://shibboleth.net/ns/attributes/naming/saml1";
+
 }
\ No newline at end of file
diff --git a/shib-saml-attribute-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/SAML2AttributeTranscoder.java b/shib-saml-attribute-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/SAML2AttributeTranscoder.java
index 171252e60..6e8a7c2d5 100644
--- a/shib-saml-attribute-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/SAML2AttributeTranscoder.java
+++ b/shib-saml-attribute-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/SAML2AttributeTranscoder.java
@@ -43,4 +43,18 @@ public interface SAML2AttributeTranscoder<EncodedType extends IdPAttributeValue>
     /** The format of the attribute name. */
     @Nonnull @NotEmpty static final String PROP_NAME_FORMAT = "saml2.nameFormat";
 
+    /**
+     * Flag to signal use of metadata to override name to encode.
+     * 
+     * @since 5.1.0
+     */
+    @Nonnull @NotEmpty static final String PROP_NAME_FROM_METADATA = "saml2.nameFromMetadata";
+
+    /**
+     * Name of metadata tag/attribute to check for in the event that {@link #PROP_NAME_FROM_METADATA} is used.
+     * 
+     * @since 5.1.0
+     */
+    @Nonnull @NotEmpty static final String METADATA_TAG_NAME = "http://shibboleth.net/ns/attributes/naming/saml2";
+
 }
\ 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