[java-shib-attribute] branch main updated: JSATTR-5 Put the NameId and NameIdenfier attribute definitions back.

Rod Widdowson rdw at steadingsoftware.com
Mon Nov 14 14:24:59 UTC 2022


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

rdw 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=b0c6ce649e2ec1f5036f54046611fb1c9e38e5e7

The following commit(s) were added to refs/heads/main by this push:
     new b0c6ce649 JSATTR-5 Put the NameId and NameIdenfier attribute definitions back.
b0c6ce649 is described below

commit b0c6ce649e2ec1f5036f54046611fb1c9e38e5e7
Author: Rod Widdowson <rdw at steadingsoftware.com>
AuthorDate: Mon Nov 14 14:23:44 2022 +0000

    JSATTR-5 Put the NameId and NameIdenfier attribute definitions back.
    
    https://shibboleth.atlassian.net/browse/JSATTR-5
    
    This reverts commit 51355ea2b410ef7bc111c205c9864d28795d5f44.
---
 ...ML1NameIdentifierAttributeDefinitionParser.java |  72 ++++++
 .../impl/SAML2NameIDAttributeDefinitionParser.java |  77 ++++++
 .../impl/AttributeResolverNamespaceHandler.java    |   8 +-
 .../schema/shibboleth-attribute-resolver.xsd       |  59 +++++
 .../resolver/spring/AttributeResolverTest.java     |   2 +-
 ...ameIdentifierAttributeDefinitionParserTest.java |  52 ++++
 ...meIDdentifierAttributeDefinitionParserTest.java |  52 ++++
 .../spring/ad/impl/SimpleAttributeParserTest.java  |   4 +-
 .../spring/ad/resolver/saml1NameIdDefault.xml      |   5 +
 .../ad/resolver/saml1NameIdentifierAttributes.xml  |   9 +
 .../spring/ad/resolver/saml2NameIdAttributes.xml   |   9 +
 .../spring/ad/resolver/saml2NameIdDefault.xml      |   3 +
 .../resolver/spring/attribute-resolver.xml         |  10 +-
 .../resolver/spring/mapperTest-attributes.xml      |   6 +
 .../SAML1NameIdentifierAttributeDefinition.java    | 224 ++++++++++++++++++
 .../impl/SAML2NameIDAttributeDefinition.java       | 261 +++++++++++++++++++++
 .../saml/attribute/resolver/impl/package-info.java |  23 ++
 17 files changed, 870 insertions(+), 6 deletions(-)

diff --git a/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/ad/impl/SAML1NameIdentifierAttributeDefinitionParser.java b/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/ad/impl/SAML1NameIdentifierAttributeDefinitionParser.java
new file mode 100644
index 000000000..4b7514591
--- /dev/null
+++ b/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/ad/impl/SAML1NameIdentifierAttributeDefinitionParser.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.attribute.resolver.spring.ad.impl;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.xml.namespace.QName;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.w3c.dom.Element;
+
+import net.shibboleth.idp.attribute.resolver.spring.ad.BaseAttributeDefinitionParser;
+import net.shibboleth.idp.attribute.resolver.spring.impl.AttributeResolverNamespaceHandler;
+import net.shibboleth.idp.saml.attribute.resolver.impl.SAML1NameIdentifierAttributeDefinition;
+import net.shibboleth.shared.primitive.DeprecationSupport;
+import net.shibboleth.shared.primitive.StringSupport;
+import net.shibboleth.shared.primitive.DeprecationSupport.ObjectType;
+
+/** Spring bean definition parser for SAML 1 NameIdentifier attribute definitions. */
+ at SuppressWarnings("removal")
+public class SAML1NameIdentifierAttributeDefinitionParser extends BaseAttributeDefinitionParser {
+
+    /** Schema type name. */
+    @Nonnull public static final QName TYPE_NAME_RESOLVER =
+            new QName(AttributeResolverNamespaceHandler.NAMESPACE, "SAML1NameIdentifier");
+
+    /** Logger. */
+    @Nonnull private final Logger log = LoggerFactory.getLogger(SAML1NameIdentifierAttributeDefinitionParser.class);
+
+    /** {@inheritDoc} */
+    @Override protected Class<SAML1NameIdentifierAttributeDefinition> getBeanClass(@Nullable final Element element) {
+        return SAML1NameIdentifierAttributeDefinition.class;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void doParse(@Nonnull final Element config, @Nonnull final ParserContext parserContext,
+            @Nonnull final BeanDefinitionBuilder builder) {        
+        DeprecationSupport.warn(ObjectType.XSITYPE, "SAML1NameIdentifier",
+                parserContext.getReaderContext().getResource().getDescription(), "(none)");
+        
+        super.doParse(config, parserContext, builder);
+
+        final String nameIdQualifier = StringSupport.trimOrNull(config.getAttributeNS(null, "nameIdQualifier"));
+        builder.addPropertyValue("nameIdQualifier", nameIdQualifier);
+
+        if (config.hasAttributeNS(null, "nameIdFormat")) {
+            final String nameIdFormat = StringSupport.trimOrNull(config.getAttributeNS(null, "nameIdFormat"));
+            log.debug("{} nameIdFormat '{}', nameIdQualifier '{}'", getLogPrefix(), nameIdFormat, nameIdQualifier);
+            builder.addPropertyValue("nameIdFormat", nameIdFormat);
+        } else {
+            log.debug("{} nameIdQualifier '{}'", getLogPrefix(), nameIdQualifier);
+        }
+    }
+}
\ No newline at end of file
diff --git a/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/ad/impl/SAML2NameIDAttributeDefinitionParser.java b/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/ad/impl/SAML2NameIDAttributeDefinitionParser.java
new file mode 100644
index 000000000..bfc82098d
--- /dev/null
+++ b/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/ad/impl/SAML2NameIDAttributeDefinitionParser.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.attribute.resolver.spring.ad.impl;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.xml.namespace.QName;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.w3c.dom.Element;
+
+import net.shibboleth.idp.attribute.resolver.spring.ad.BaseAttributeDefinitionParser;
+import net.shibboleth.idp.attribute.resolver.spring.impl.AttributeResolverNamespaceHandler;
+import net.shibboleth.idp.saml.attribute.resolver.impl.SAML2NameIDAttributeDefinition;
+import net.shibboleth.shared.primitive.DeprecationSupport;
+import net.shibboleth.shared.primitive.StringSupport;
+import net.shibboleth.shared.primitive.DeprecationSupport.ObjectType;
+
+/** Spring bean definition parser for SAML 2 NameID attribute definitions. */
+ at SuppressWarnings("removal")
+public class SAML2NameIDAttributeDefinitionParser extends BaseAttributeDefinitionParser {
+
+    /** Schema type name. */
+    @Nonnull public static final QName TYPE_NAME_RESOLVER =
+            new QName(AttributeResolverNamespaceHandler.NAMESPACE, "SAML2NameID");
+
+    /** Logger. */
+    @Nonnull private final Logger log = LoggerFactory.getLogger(SAML1NameIdentifierAttributeDefinitionParser.class);
+
+    /** {@inheritDoc} */
+    @Override protected Class<SAML2NameIDAttributeDefinition> getBeanClass(@Nullable final Element element) {
+        return SAML2NameIDAttributeDefinition.class;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void doParse(@Nonnull final Element config, @Nonnull final ParserContext parserContext,
+            @Nonnull final BeanDefinitionBuilder builder) {
+        DeprecationSupport.warn(ObjectType.XSITYPE, "SAML2NameID",
+                parserContext.getReaderContext().getResource().getDescription(), "(none)");
+
+        super.doParse(config, parserContext, builder);
+
+        if (config.hasAttributeNS(null, "nameIdFormat")) {
+            final String nameIdFormat = StringSupport.trimOrNull(config.getAttributeNS(null, "nameIdFormat"));
+            builder.addPropertyValue("nameIdFormat", nameIdFormat);
+            log.debug("{} nameIdFormat '{}'", getLogPrefix(), nameIdFormat);
+        }
+
+        final String nameIdQualifier = StringSupport.trimOrNull(config.getAttributeNS(null, "nameIdQualifier"));
+        builder.addPropertyValue("nameIdQualifier", nameIdQualifier);
+
+        final String nameIdSPQualifier = StringSupport.trimOrNull(config.getAttributeNS(null, "nameIdSPQualifier"));
+        builder.addPropertyValue("nameIdSPQualifier", nameIdSPQualifier);
+
+        log.debug("{} nameIdQualifier '{}', nameIdSPQualifier '{}'", getLogPrefix(), nameIdQualifier,
+                nameIdSPQualifier);
+    }
+
+}
\ No newline at end of file
diff --git a/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/impl/AttributeResolverNamespaceHandler.java b/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/impl/AttributeResolverNamespaceHandler.java
index 8640a3791..68e8b1f1f 100644
--- a/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/impl/AttributeResolverNamespaceHandler.java
+++ b/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/impl/AttributeResolverNamespaceHandler.java
@@ -23,13 +23,15 @@ import org.springframework.beans.factory.xml.BeanDefinitionParser;
 
 import net.shibboleth.idp.attribute.resolver.spring.ad.impl.ContextDerivedAttributeDefinitionParser;
 import net.shibboleth.idp.attribute.resolver.spring.ad.impl.DateTimeAttributeDefinitionParser;
-import net.shibboleth.idp.attribute.resolver.spring.ad.impl.DecryptedAttributeDefinitionParser;
 import net.shibboleth.idp.attribute.resolver.spring.ad.impl.PrescopedAttributeDefinitionParser;
 import net.shibboleth.idp.attribute.resolver.spring.ad.impl.PrincipalNameAttributeDefinitionParser;
 import net.shibboleth.idp.attribute.resolver.spring.ad.impl.RegexSplitAttributeDefinitionParser;
+import net.shibboleth.idp.attribute.resolver.spring.ad.impl.SAML1NameIdentifierAttributeDefinitionParser;
+import net.shibboleth.idp.attribute.resolver.spring.ad.impl.SAML2NameIDAttributeDefinitionParser;
 import net.shibboleth.idp.attribute.resolver.spring.ad.impl.ScopedAttributeDefinitionParser;
 import net.shibboleth.idp.attribute.resolver.spring.ad.impl.ScriptedAttributeDefinitionParser;
 import net.shibboleth.idp.attribute.resolver.spring.ad.impl.SimpleAttributeDefinitionParser;
+import net.shibboleth.idp.attribute.resolver.spring.ad.impl.DecryptedAttributeDefinitionParser;
 import net.shibboleth.idp.attribute.resolver.spring.ad.impl.SubjectDerivedAttributeDefinitionParser;
 import net.shibboleth.idp.attribute.resolver.spring.ad.impl.TemplateAttributeDefinitionParser;
 import net.shibboleth.idp.attribute.resolver.spring.ad.mapped.impl.MappedAttributeDefinitionParser;
@@ -85,6 +87,10 @@ public class AttributeResolverNamespaceHandler extends BaseSpringNamespaceHandle
                 new SubjectDerivedAttributeDefinitionParser());
         registerBeanDefinitionParser(ContextDerivedAttributeDefinitionParser.TYPE_NAME_RESOLVER,
                 new ContextDerivedAttributeDefinitionParser());
+        registerBeanDefinitionParser(SAML1NameIdentifierAttributeDefinitionParser.TYPE_NAME_RESOLVER,
+                new SAML1NameIdentifierAttributeDefinitionParser());
+        registerBeanDefinitionParser(SAML2NameIDAttributeDefinitionParser.TYPE_NAME_RESOLVER,
+                new SAML2NameIDAttributeDefinitionParser());
         registerBeanDefinitionParser(ScopedAttributeDefinitionParser.TYPE_NAME_RESOLVER,
                 new ScopedAttributeDefinitionParser());
         registerBeanDefinitionParser(ScriptedAttributeDefinitionParser.TYPE_NAME_RESOLVER,
diff --git a/shib-attribute-resolver-spring/src/main/resources/schema/shibboleth-attribute-resolver.xsd b/shib-attribute-resolver-spring/src/main/resources/schema/shibboleth-attribute-resolver.xsd
index 9f2ffa194..78bec7ee4 100644
--- a/shib-attribute-resolver-spring/src/main/resources/schema/shibboleth-attribute-resolver.xsd
+++ b/shib-attribute-resolver-spring/src/main/resources/schema/shibboleth-attribute-resolver.xsd
@@ -453,6 +453,65 @@
         </complexContent>
     </complexType>
 
+    <complexType name="SAML1NameIdentifier">
+        <annotation>
+            <documentation>An attribute definition that creates attributes whose values are SAML 1 NameIdentifiers.</documentation>
+        </annotation>
+        <complexContent>
+            <extension base="resolver:BaseAttributeDefinitionType">
+                <choice maxOccurs="unbounded" minOccurs="0">
+                    <element ref="resolver:InputAttributeDefinition"/>
+                    <element ref="resolver:InputDataConnector"/>
+                    <element name="DisplayName" type="resolver:LocalizedStringType"/>
+                    <element name="DisplayDescription" type="resolver:LocalizedStringType"/>
+                    <element ref="resolver:AttributeEncoder"/>
+                </choice>
+                <attribute name="nameIdFormat" type="resolver:string">
+                    <annotation>
+                        <documentation>The SAML 1 NameFormat of the NameID.</documentation>
+                    </annotation>
+                </attribute>
+                <attribute name="nameIdQualifier" type="resolver:string">
+                    <annotation>
+                        <documentation>The SAML 1 NameQualifier of the NameID.</documentation>
+                    </annotation>
+                </attribute>
+            </extension>
+        </complexContent>
+    </complexType>
+
+    <complexType name="SAML2NameID">
+        <annotation>
+            <documentation>An attribute definition that creates attributes whose values are SAML 2 NameIDs.</documentation>
+        </annotation>
+        <complexContent>
+            <extension base="resolver:BaseAttributeDefinitionType">
+                <choice maxOccurs="unbounded" minOccurs="0">
+                    <element ref="resolver:InputAttributeDefinition"/>
+                    <element ref="resolver:InputDataConnector"/>
+                    <element name="DisplayName" type="resolver:LocalizedStringType"/>
+                    <element name="DisplayDescription" type="resolver:LocalizedStringType"/>
+                    <element ref="resolver:AttributeEncoder"/>
+                </choice>
+                <attribute name="nameIdFormat" type="resolver:string">
+                    <annotation>
+                        <documentation>The SAML 2 NameFormat of the NameID.</documentation>
+                    </annotation>
+                </attribute>
+                <attribute name="nameIdQualifier" type="resolver:string">
+                    <annotation>
+                        <documentation>The SAML 2 NameQualifier of the NameID.</documentation>
+                    </annotation>
+                </attribute>
+                <attribute name="nameIdSPQualifier" type="resolver:string">
+                    <annotation>
+                        <documentation>The SAML 2 SPNameQualifier of the NameID.</documentation>
+                    </annotation>
+                </attribute>
+            </extension>
+        </complexContent>
+    </complexType>
+
     <complexType name="Scoped">
         <annotation>
             <documentation>A basic attribute definition which supports attribute scoping.</documentation>
diff --git a/shib-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/AttributeResolverTest.java b/shib-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/AttributeResolverTest.java
index cee5087fd..9f7bcd89f 100644
--- a/shib-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/AttributeResolverTest.java
+++ b/shib-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/AttributeResolverTest.java
@@ -275,7 +275,7 @@ public class AttributeResolverTest extends OpenSAMLInitBaseTestCase {
         assertTrue(values.contains(new StringAttributeValue("555-111-2222")));
 
         // Computed
-        attribute = resolvedAttributes.get("computedID");
+        attribute = resolvedAttributes.get("eduPersonTargetedID");
         assertNotNull(attribute);
         values = attribute.getValues();
         assertEquals(values.size(), 1);
diff --git a/shib-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/ad/impl/SAML1NameIdentifierAttributeDefinitionParserTest.java b/shib-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/ad/impl/SAML1NameIdentifierAttributeDefinitionParserTest.java
new file mode 100644
index 000000000..78cb312df
--- /dev/null
+++ b/shib-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/ad/impl/SAML1NameIdentifierAttributeDefinitionParserTest.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.attribute.resolver.spring.ad.impl;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+
+import org.testng.annotations.Test;
+
+import net.shibboleth.idp.attribute.resolver.spring.testing.BaseAttributeDefinitionParserTest;
+import net.shibboleth.idp.saml.attribute.resolver.impl.SAML1NameIdentifierAttributeDefinition;
+
+/**
+ * Test for {@link SAML1NameIdentifierAttributeDefinitionParser}.
+ */
+ at SuppressWarnings("javadoc")
+public class SAML1NameIdentifierAttributeDefinitionParserTest extends BaseAttributeDefinitionParserTest {
+
+    @Test public void defaultCase() {
+        SAML1NameIdentifierAttributeDefinition attrDef =
+                getAttributeDefn("resolver/saml1NameIdDefault.xml", SAML1NameIdentifierAttributeDefinition.class);
+
+        assertEquals(attrDef.getId(), "SAML1NameIdentifier");
+        assertEquals(attrDef.getNameIdFormat(), "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified");
+        assertNull(attrDef.getNameIdQualifier());
+    }
+
+    @Test public void attributes() {
+        SAML1NameIdentifierAttributeDefinition attrDef = getAttributeDefn("resolver/saml1NameIdentifierAttributes.xml",
+                SAML1NameIdentifierAttributeDefinition.class);
+
+        assertEquals(attrDef.getId(), "SAML1NameIdentifierAttributes");
+        assertEquals(attrDef.getNameIdFormat(), "format");
+        assertEquals(attrDef.getNameIdQualifier(), "qualifier");
+    }
+
+}
diff --git a/shib-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/ad/impl/SAML2NameIDdentifierAttributeDefinitionParserTest.java b/shib-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/ad/impl/SAML2NameIDdentifierAttributeDefinitionParserTest.java
new file mode 100644
index 000000000..024f79039
--- /dev/null
+++ b/shib-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/ad/impl/SAML2NameIDdentifierAttributeDefinitionParserTest.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.attribute.resolver.spring.ad.impl;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+
+import org.testng.annotations.Test;
+
+import net.shibboleth.idp.attribute.resolver.spring.testing.BaseAttributeDefinitionParserTest;
+import net.shibboleth.idp.saml.attribute.resolver.impl.SAML2NameIDAttributeDefinition;
+
+/**
+ * Test for {@link SAML1NameIdentifierAttributeDefinitionParser}.
+ */
+ at SuppressWarnings("javadoc")
+public class SAML2NameIDdentifierAttributeDefinitionParserTest extends BaseAttributeDefinitionParserTest {
+
+    @Test public void defaultCase() {
+        SAML2NameIDAttributeDefinition attrDef =
+                getAttributeDefn("resolver/saml2NameIdDefault.xml", SAML2NameIDAttributeDefinition.class);
+
+        assertEquals(attrDef.getId(), "SAML2NameID");
+        assertEquals(attrDef.getNameIdFormat(), "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified");
+        assertNull(attrDef.getNameIdQualifier());
+    }
+
+    @Test public void attributes() {
+        SAML2NameIDAttributeDefinition attrDef =
+                getAttributeDefn("resolver/saml2NameIdAttributes.xml", SAML2NameIDAttributeDefinition.class);
+
+        assertEquals(attrDef.getId(), "SAML2NameId-Attr");
+        assertEquals(attrDef.getNameIdFormat(), "format");
+        assertEquals(attrDef.getNameIdQualifier(), "qualifier");
+        assertEquals(attrDef.getNameIdSPQualifier(), "name-Id-SP-Qualifier");
+    }
+}
diff --git a/shib-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/ad/impl/SimpleAttributeParserTest.java b/shib-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/ad/impl/SimpleAttributeParserTest.java
index 8721650e3..d84de6fa1 100644
--- a/shib-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/ad/impl/SimpleAttributeParserTest.java
+++ b/shib-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/ad/impl/SimpleAttributeParserTest.java
@@ -17,9 +17,7 @@
 
 package net.shibboleth.idp.attribute.resolver.spring.ad.impl;
 
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.*;
 
 import java.util.Collection;
 import java.util.Map;
diff --git a/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/ad/resolver/saml1NameIdDefault.xml b/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/ad/resolver/saml1NameIdDefault.xml
new file mode 100644
index 000000000..bdb8c4570
--- /dev/null
+++ b/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/ad/resolver/saml1NameIdDefault.xml
@@ -0,0 +1,5 @@
+ <AttributeDefinition  xmlns="urn:mace:shibboleth:2.0:resolver" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ 	xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd" 
+ 
+    dependencyOnly="1"
+    xsi:type="SAML1NameIdentifier" id="SAML1NameIdentifier"/>
diff --git a/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/ad/resolver/saml1NameIdentifierAttributes.xml b/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/ad/resolver/saml1NameIdentifierAttributes.xml
new file mode 100644
index 000000000..b1ecf1900
--- /dev/null
+++ b/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/ad/resolver/saml1NameIdentifierAttributes.xml
@@ -0,0 +1,9 @@
+ <AttributeDefinition 
+    xmlns="urn:mace:shibboleth:2.0:resolver"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+    dependencyOnly="1"
+    xsi:type="SAML1NameIdentifier" id="SAML1NameIdentifierAttributes"
+    nameIdFormat = "format" 
+    nameIdQualifier = "qualifier"
+    xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd"
+    />
diff --git a/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/ad/resolver/saml2NameIdAttributes.xml b/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/ad/resolver/saml2NameIdAttributes.xml
new file mode 100644
index 000000000..18660694e
--- /dev/null
+++ b/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/ad/resolver/saml2NameIdAttributes.xml
@@ -0,0 +1,9 @@
+ <AttributeDefinition 
+    xmlns="urn:mace:shibboleth:2.0:resolver"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+    xsi:type="SAML2NameID" id="SAML2NameId-Attr"
+    nameIdFormat = "format" 
+    nameIdQualifier = "qualifier"
+    nameIdSPQualifier = "name-Id-SP-Qualifier"
+    xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd"
+    />
diff --git a/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/ad/resolver/saml2NameIdDefault.xml b/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/ad/resolver/saml2NameIdDefault.xml
new file mode 100644
index 000000000..c18976d80
--- /dev/null
+++ b/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/ad/resolver/saml2NameIdDefault.xml
@@ -0,0 +1,3 @@
+ <AttributeDefinition xmlns="urn:mace:shibboleth:2.0:resolver" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+    xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd"
+    xsi:type="SAML2NameID" id="SAML2NameID" />
diff --git a/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/attribute-resolver.xml b/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/attribute-resolver.xml
index 1fdb95d57..4bf0564c6 100644
--- a/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/attribute-resolver.xml
+++ b/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/attribute-resolver.xml
@@ -196,6 +196,14 @@
         <AttributeEncoder xsi:type="SAML2String" name="urn:oid:2.16.840.1.113730.3.1.39" friendlyName="preferredLanguage" />
     </AttributeDefinition>
     
+
+    <AttributeDefinition xsi:type="SAML2NameID" id="eduPersonTargetedID" 
+                                  nameIdFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">
+        <InputDataConnector ref="computedID" attributeNames="computedID"/>
+        <AttributeEncoder xsi:type="SAML1XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" />
+        <AttributeEncoder xsi:type="SAML2XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" friendlyName="eduPersonTargetedID" />
+    </AttributeDefinition>
+    
     <!-- ========================================== -->
     <!--      Data Connectors                       -->
     <!-- ========================================== -->
@@ -240,7 +248,7 @@
     </DataConnector>
     <!-- Computed targeted ID connector -->
 
-    <DataConnector xsi:type="ComputedId" exportAttributes="computedID"
+    <DataConnector xsi:type="ComputedId"
         id="computedID" generatedAttributeID="computedID"
         salt="your random string here">
         <InputDataConnector ref="myLDAP" attributeNames="uid"/>
diff --git a/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/mapperTest-attributes.xml b/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/mapperTest-attributes.xml
index 04be212b4..2c4c4357d 100644
--- a/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/mapperTest-attributes.xml
+++ b/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/mapperTest-attributes.xml
@@ -50,4 +50,10 @@
         <DisplayDescription xml:lang="fr-CA">Le Color</DisplayDescription>
     </AttributeDefinition>
     
+    <AttributeDefinition xsi:type="SAML2NameID" id="eduPersonTID" 
+                                  nameIdFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" >
+        <InputDataConnector allAttributes="true"  ref="myLDAP" />
+        <AttributeEncoder xsi:type="SAML1XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" />
+        <AttributeEncoder xsi:type="SAML2XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" friendlyName="feduPersonTargetedID" />
+    </AttributeDefinition>
 </AttributeResolver>
diff --git a/shib-saml-attribute-impl/src/main/java/net/shibboleth/idp/saml/attribute/resolver/impl/SAML1NameIdentifierAttributeDefinition.java b/shib-saml-attribute-impl/src/main/java/net/shibboleth/idp/saml/attribute/resolver/impl/SAML1NameIdentifierAttributeDefinition.java
new file mode 100644
index 000000000..6f4431233
--- /dev/null
+++ b/shib-saml-attribute-impl/src/main/java/net/shibboleth/idp/saml/attribute/resolver/impl/SAML1NameIdentifierAttributeDefinition.java
@@ -0,0 +1,224 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.saml.attribute.resolver.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.saml.common.SAMLObjectBuilder;
+import org.opensaml.saml.saml1.core.NameIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.StringAttributeValue;
+import net.shibboleth.idp.attribute.XMLObjectAttributeValue;
+import net.shibboleth.idp.attribute.resolver.AbstractAttributeDefinition;
+import net.shibboleth.idp.attribute.resolver.PluginDependencySupport;
+import net.shibboleth.idp.attribute.resolver.ResolutionException;
+import net.shibboleth.idp.attribute.resolver.context.AttributeResolutionContext;
+import net.shibboleth.idp.attribute.resolver.context.AttributeResolverWorkContext;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.primitive.StringSupport;
+
+/**
+ * An attribute definition the creates attributes whose values are {@link NameIdentifier}.
+ * 
+ * <p>When building the NameIdentifier the textual content of the NameIdentifier is the value of the source attribute.
+ * If {@link #getNameIdQualifier()} is non-null, then that value is used as the NameIdentifier's NameQualifier otherwise
+ * the attribute issuer's entityID is used.</p>
+ * 
+ * @deprecated
+ */
+ at Deprecated(forRemoval=true, since="4.1.0")
+public class SAML1NameIdentifierAttributeDefinition extends AbstractAttributeDefinition {
+
+    /** Class logger. */
+    @Nonnull private final Logger log = LoggerFactory.getLogger(SAML1NameIdentifierAttributeDefinition.class);
+
+    /** The builder for the object represented inside this attribute. */
+    @Nonnull private final SAMLObjectBuilder<NameIdentifier> nameIdentifierBuilder;
+
+    /** Format of the NameID. */
+    private String nameIdFormat;
+
+    /** Name qualifier for the NameID. */
+    private String nameIdQualifier;
+
+    /**
+     * Constructor.
+     */
+    public SAML1NameIdentifierAttributeDefinition() {
+        nameIdentifierBuilder = (SAMLObjectBuilder<NameIdentifier>)
+                XMLObjectProviderRegistrySupport.getBuilderFactory().<NameIdentifier>getBuilderOrThrow(
+                        NameIdentifier.DEFAULT_ELEMENT_NAME);
+        nameIdFormat = NameIdentifier.UNSPECIFIED;
+    }
+
+    /**
+     * Gets the format for the NameID used as an attribute value.
+     * 
+     * @return format for the NameID used as an attribute value
+     */
+    @Nullable public String getNameIdFormat() {
+        return nameIdFormat;
+    }
+
+    /**
+     * Sets the format for the NameID used as an attribute value.
+     * 
+     * @param format format for the NameID used as an attribute value
+     */
+    public void setNameIdFormat(@Nullable final String format) {
+        checkSetterPreconditions();
+        nameIdFormat = format;
+    }
+
+    /**
+     * Gets the NameQualifier for the NameID used as an attribute value.
+     * 
+     * @return NameQualifier for the NameID used as an attribute value
+     */
+    @Nullable public String getNameIdQualifier() {
+        return nameIdQualifier;
+    }
+
+    /**
+     * Sets the NameQualifier for the NameID used as an attribute value.
+     * 
+     * @param qualifier NameQualifier for the NameID used as an attribute value
+     */
+    public void setNameIdQualifier(@Nullable final String qualifier) {
+        checkSetterPreconditions();
+        nameIdQualifier = qualifier;
+    }
+
+    /**
+     * Builds a name ID. The provided value is the textual content of the NameIdentifier. If 
+     * {@link #getNameIdQualifier()} is not null it is used as the NameIdentifier's name qualifier,
+     * otherwise the attribute issuer's entityID is used.
+     * 
+     * @param nameIdValue value of the NameIdentifier
+     * @param resolutionContext current resolution context
+     * 
+     * @return the constructed NameIdentifier
+     * @throws ResolutionException if the IdP Name is empty.
+     */
+    protected NameIdentifier buildNameId(@Nonnull @NotEmpty final String nameIdValue,
+            @Nonnull final AttributeResolutionContext resolutionContext) throws ResolutionException {
+
+        log.debug("{} building a SAML1 NameIdentifier with value of '{}'", getLogPrefix(), nameIdValue);
+
+        final NameIdentifier nameIdentifier = nameIdentifierBuilder.buildObject();
+        nameIdentifier.setValue(nameIdValue);
+
+        if (nameIdFormat != null) {
+            log.debug("{} Format set to '{}'", getLogPrefix(), nameIdFormat);
+            nameIdentifier.setFormat(nameIdFormat);
+        }
+        final String attributeIssuerID = StringSupport.trimOrNull(resolutionContext.getAttributeIssuerID());
+
+        if (nameIdQualifier != null) {
+            nameIdentifier.setNameQualifier(nameIdQualifier);
+            log.debug("{} NameQualifier set to '{}'", getLogPrefix(), nameIdQualifier);
+        } else if (null != attributeIssuerID) {
+            log.debug("{} NameQualifier set to '{}'", getLogPrefix(), attributeIssuerID);
+            nameIdentifier.setNameQualifier(attributeIssuerID);
+        } else {
+            throw new ResolutionException(getLogPrefix() + " provided attribute issuer ID was empty");
+        }
+
+        return nameIdentifier;
+    }
+
+    /**
+     * Worker function for doAttributeDefintionResolve. This returns an AttributeValue if the input value is appropriate
+     * for encoding as a NameID.
+     * 
+     * @param theValue an arbitrary value.
+     * @param resolutionContext the context to get the rest of the values from
+     * @return null or an attributeValue;
+     * @throws ResolutionException if the IdP Name is empty.
+     */
+    @Nullable private XMLObjectAttributeValue encodeOneValue(@Nonnull final IdPAttributeValue theValue,
+            @Nonnull final AttributeResolutionContext resolutionContext) throws ResolutionException {
+
+        if (theValue instanceof StringAttributeValue) {
+            final String value = StringSupport.trimOrNull(((StringAttributeValue) theValue).getValue());
+            if (value == null) {
+                log.warn("{} Value was all whitespace", getLogPrefix());
+                return null;
+            }
+            final NameIdentifier nid = buildNameId(value, resolutionContext);
+            final XMLObjectAttributeValue val = new XMLObjectAttributeValue(nid);
+            return val;
+        }
+        log.warn("{} Unsupported value type: {}", getLogPrefix(), theValue.getClass().getName());
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override @Nullable protected IdPAttribute doAttributeDefinitionResolve(
+            @Nonnull final AttributeResolutionContext resolutionContext,
+            @Nonnull final AttributeResolverWorkContext workContext) throws ResolutionException {
+
+        checkComponentActive();
+        final List<? extends IdPAttributeValue> inputValues;
+        List<IdPAttributeValue> outputValues = null;
+        final IdPAttribute result = new IdPAttribute(getId());
+
+        inputValues = PluginDependencySupport.getMergedAttributeValues(workContext,
+                getAttributeDependencies(),
+                getDataConnectorDependencies(),
+                getId());
+
+        if (null != inputValues && !inputValues.isEmpty()) {
+            if (1 == inputValues.size()) {
+                final IdPAttributeValue val = encodeOneValue(inputValues.iterator().next(), resolutionContext);
+                if (null != val) {
+                    outputValues = Collections.singletonList(val);
+                }
+            } else {
+                // TODO(rdw) Fix typing
+                // Intermediate to solve typing issues.
+                final List<IdPAttributeValue> xmlVals = new ArrayList<>(inputValues.size());
+                for (final IdPAttributeValue theValue : inputValues) {
+                    final XMLObjectAttributeValue val = encodeOneValue(theValue, resolutionContext);
+                    if (null != val) {
+                        xmlVals.add(val);
+                    }
+                }
+                if (0 == xmlVals.size()) {
+                    log.warn("{} No appropriate values", getLogPrefix());
+                    return null;
+                }
+                outputValues = xmlVals;
+            }
+        }
+        result.setValues(outputValues);
+
+        return result;
+    }
+
+}
diff --git a/shib-saml-attribute-impl/src/main/java/net/shibboleth/idp/saml/attribute/resolver/impl/SAML2NameIDAttributeDefinition.java b/shib-saml-attribute-impl/src/main/java/net/shibboleth/idp/saml/attribute/resolver/impl/SAML2NameIDAttributeDefinition.java
new file mode 100644
index 000000000..45fe78677
--- /dev/null
+++ b/shib-saml-attribute-impl/src/main/java/net/shibboleth/idp/saml/attribute/resolver/impl/SAML2NameIDAttributeDefinition.java
@@ -0,0 +1,261 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.saml.attribute.resolver.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.saml.common.SAMLObjectBuilder;
+import org.opensaml.saml.saml2.core.NameID;
+import org.opensaml.saml.saml2.core.NameIDType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.StringAttributeValue;
+import net.shibboleth.idp.attribute.XMLObjectAttributeValue;
+import net.shibboleth.idp.attribute.resolver.AbstractAttributeDefinition;
+import net.shibboleth.idp.attribute.resolver.PluginDependencySupport;
+import net.shibboleth.idp.attribute.resolver.ResolutionException;
+import net.shibboleth.idp.attribute.resolver.context.AttributeResolutionContext;
+import net.shibboleth.idp.attribute.resolver.context.AttributeResolverWorkContext;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.primitive.StringSupport;
+
+/**
+ * An attribute definition that creates attributes whose values are {@link NameID}.
+ * 
+ * <p>When building the NameID the textual content of the NameID is the value of the source attribute. If a
+ * {@link #getNameIdQualifier()} is non-null, then that value is used as the NameID's NameQualifier otherwise
+ * the attribute issuer's entityID is used. If {@link #getNameIdSPQualifier()} is non-null, then that valid is
+ * used as the NameID's SPNameQualifier, otherwise the attribute recipient's entityID is used.</p>
+ * 
+ * @deprecated
+ */
+ at Deprecated(forRemoval=true, since="4.1.0")
+public class SAML2NameIDAttributeDefinition extends AbstractAttributeDefinition {
+
+    /** Class logger. */
+    @Nonnull private final Logger log = LoggerFactory.getLogger(SAML2NameIDAttributeDefinition.class);
+
+    /** The builder for the object represented inside this attribute. */
+    @Nonnull private final SAMLObjectBuilder<NameID> nameIDBuilder;
+
+    /** Format of the NameID. */
+    private String nameIdFormat;
+
+    /** Name qualifier for the NameID. */
+    private String nameIdQualifier;
+
+    /** SP name qualifier for the NameID. */
+    private String nameIdSPQualifier;
+
+    /**
+     * Constructor.
+     */
+    public SAML2NameIDAttributeDefinition() {
+        nameIDBuilder = (SAMLObjectBuilder<NameID>)
+                XMLObjectProviderRegistrySupport.getBuilderFactory().<NameID>getBuilderOrThrow(
+                        NameID.DEFAULT_ELEMENT_NAME);
+        nameIdFormat = NameIDType.UNSPECIFIED;
+    }
+
+    /**
+     * Gets the format for the NameID used as an attribute value.
+     * 
+     * @return format for the NameID used as an attribute value
+     */
+    @Nullable public String getNameIdFormat() {
+        return nameIdFormat;
+    }
+
+    /**
+     * Sets the format for the NameID used as an attribute value.
+     * 
+     * @param format format for the NameID used as an attribute value
+     */
+    public void setNameIdFormat(@Nullable final String format) {
+        checkSetterPreconditions();
+        nameIdFormat = format;
+    }
+
+    /**
+     * Gets the NameQualifier for the NameID used as an attribute value.
+     * 
+     * @return NameQualifier for the NameID used as an attribute value
+     */
+    @Nullable public String getNameIdQualifier() {
+        return nameIdQualifier;
+    }
+
+    /**
+     * Sets the NameQualifier for the NameID used as an attribute value.
+     * 
+     * @param qualifier NameQualifier for the NameID used as an attribute value
+     */
+    public void setNameIdQualifier(@Nullable final String qualifier) {
+        checkSetterPreconditions();
+        nameIdQualifier = qualifier;
+    }
+
+    /**
+     * Gets the SPNameQualifier for the NameID used as an attribute value.
+     * 
+     * @return SPNameQualifier for the NameID used as an attribute value
+     */
+    @Nullable public String getNameIdSPQualifier() {
+        return nameIdSPQualifier;
+    }
+
+    /**
+     * Sets the SPNameQualifier for the NameID used as an attribute value.
+     * 
+     * @param qualifier SPNameQualifier for the NameID used as an attribute value
+     */
+    public void setNameIdSPQualifier(@Nullable final String qualifier) {
+        checkSetterPreconditions();
+        nameIdSPQualifier = qualifier;
+    }
+
+    /**
+     * Builds a name ID. The provided value is the textual content of the NameID. The NameQualifier and SPNameQualifier
+     * are set according to the configuration, or to the local and requesting entityIDs respectively.
+     * 
+     * @param nameIdValue value of the NameID
+     * @param resolutionContext current resolution context
+     * 
+     * @return the constructed NameID
+     * @throws ResolutionException if the IdP Name is empty.
+     */
+    protected NameID buildNameId(@Nonnull @NotEmpty final String nameIdValue,
+            @Nonnull final AttributeResolutionContext resolutionContext) throws ResolutionException {
+
+        log.debug("{} building a SAML2 NameID with value of '{}'", getLogPrefix(), nameIdValue);
+
+        final String attributeRecipientID =
+                StringSupport.trimOrNull(resolutionContext.getAttributeRecipientID());
+
+        final String attributeIssuerID = StringSupport.trimOrNull(resolutionContext.getAttributeIssuerID());
+
+        final NameID nameId = nameIDBuilder.buildObject();
+        nameId.setValue(nameIdValue);
+
+        if (nameIdFormat != null) {
+            log.debug("{} Format set to '{}'", getLogPrefix(), nameIdFormat);
+            nameId.setFormat(nameIdFormat);
+        }
+
+        if (nameIdQualifier != null) {
+            log.debug("{} NameQualifier set to '{}'", getLogPrefix(), nameIdQualifier);
+            nameId.setNameQualifier(nameIdQualifier);
+        } else if (null != attributeIssuerID) {
+            log.debug("{} NameQualifier set to '{}'", getLogPrefix(), attributeIssuerID);
+            nameId.setNameQualifier(attributeIssuerID);
+        } else {
+            throw new ResolutionException(getLogPrefix() + " provided attribute issuer ID  was empty");
+        }
+
+        if (nameIdSPQualifier != null) {
+            log.debug("{} SPNameQualifier set to '{}'", getLogPrefix(), nameIdSPQualifier);
+            nameId.setSPNameQualifier(nameIdSPQualifier);
+        } else if (null != attributeRecipientID) {
+            log.debug("{} SPNameQualifier set to '{}'", getLogPrefix(), attributeRecipientID);
+            nameId.setSPNameQualifier(attributeRecipientID);
+        } else {
+            throw new ResolutionException(getLogPrefix() + " provided attribute recipient ID was empty");
+        }
+
+        return nameId;
+    }
+
+    /**
+     * Worker function for doAttributeDefintionResolve. This returns an AttributeValue if the input value is appropriate
+     * for encoding as a NameID.
+     * 
+     * @param theValue an arbitrary value.
+     * @param resolutionContext the context to get the rest of the values from
+     * @return null or an attributeValue.
+     * @throws ResolutionException if the IdP Name is empty.
+     */
+    @Nullable private XMLObjectAttributeValue encodeOneValue(@Nonnull final IdPAttributeValue theValue,
+            @Nonnull final AttributeResolutionContext resolutionContext) throws ResolutionException {
+        if (theValue instanceof StringAttributeValue) {
+            final String value = StringSupport.trimOrNull(((StringAttributeValue) theValue).getValue());
+            if (value == null) {
+                log.warn("{} Value was all whitespace", getLogPrefix());
+                return null;
+            }
+            final NameID nid = buildNameId(value, resolutionContext);
+            final XMLObjectAttributeValue val = new XMLObjectAttributeValue(nid);
+            return val;
+        }
+        log.warn("{} Unsupported value type: {}", getLogPrefix(), theValue.getClass().getName());
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override @Nullable protected IdPAttribute doAttributeDefinitionResolve(
+            @Nonnull final AttributeResolutionContext resolutionContext,
+            @Nonnull final AttributeResolverWorkContext workContext) throws ResolutionException {
+
+        checkComponentActive();
+        final List<IdPAttributeValue> inputValues;
+        List<IdPAttributeValue> outputValues = null;
+        final IdPAttribute result = new IdPAttribute(getId());
+
+        inputValues = PluginDependencySupport.getMergedAttributeValues(workContext,
+                getAttributeDependencies(),
+                getDataConnectorDependencies(),
+                getId());
+
+        if (null != inputValues && !inputValues.isEmpty()) {
+
+            if (1 == inputValues.size()) {
+                final IdPAttributeValue val = encodeOneValue(inputValues.iterator().next(), resolutionContext);
+                if (null != val) {
+                    outputValues = Collections.singletonList(val);
+                }
+            } else {
+                // TODO Intermediate to solve typing issues.
+                final List<IdPAttributeValue> xmlVals = new ArrayList<>(inputValues.size());
+                for (final IdPAttributeValue theValue : inputValues) {
+                    final XMLObjectAttributeValue val = encodeOneValue(theValue, resolutionContext);
+                    if (null != val) {
+                        xmlVals.add(val);
+                    }
+                }
+                if (0 == xmlVals.size()) {
+                    log.warn("{} No appropriate values", getLogPrefix());
+                    return null;
+                }
+                outputValues = xmlVals;
+            }
+        }
+        result.setValues(outputValues);
+
+        return result;
+
+    }
+
+}
diff --git a/shib-saml-attribute-impl/src/main/java/net/shibboleth/idp/saml/attribute/resolver/impl/package-info.java b/shib-saml-attribute-impl/src/main/java/net/shibboleth/idp/saml/attribute/resolver/impl/package-info.java
new file mode 100644
index 000000000..1ea048a02
--- /dev/null
+++ b/shib-saml-attribute-impl/src/main/java/net/shibboleth/idp/saml/attribute/resolver/impl/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Implementations of SAML related {@link net.shibboleth.idp.attribute.resolver.AttributeDefinition}
+ * and {@link net.shibboleth.idp.attribute.resolver.DataConnector}.
+ */
+
+package net.shibboleth.idp.saml.attribute.resolver.impl;
\ 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