Updated properties sync to use a mapping defined in the OSGI configs such that the name and relative path of the save property can be configured (instead of using the saml attribute's Friendly Name)
diff --git a/saml-handler/src/main/java/org/apache/sling/auth/saml2/AuthenticationHandlerSAML2Config.java b/saml-handler/src/main/java/org/apache/sling/auth/saml2/AuthenticationHandlerSAML2Config.java
index 4b0ac3b..7b16619 100644
--- a/saml-handler/src/main/java/org/apache/sling/auth/saml2/AuthenticationHandlerSAML2Config.java
+++ b/saml-handler/src/main/java/org/apache/sling/auth/saml2/AuthenticationHandlerSAML2Config.java
@@ -66,7 +66,7 @@
     String saml2groupMembershipAttr() default "";
 
     @AttributeDefinition(name = "Synchronize User Attributes",
-            description="List of Names from SAML Response to Synchronize")
+            description="Map of attributes from SAML Response to Synchronize. For example, urn:oid:1.2.840.113549.1.9.1=./profile/email saves this attribute if it exists under the users profile node with the property name 'email' ")
     String[] syncAttrs() default {};
 
     @AttributeDefinition(name = "SAML2 Session Attribute",
diff --git a/saml-handler/src/main/java/org/apache/sling/auth/saml2/impl/AbstractSamlHandler.java b/saml-handler/src/main/java/org/apache/sling/auth/saml2/impl/AbstractSamlHandler.java
index 7f365c4..719cbbb 100644
--- a/saml-handler/src/main/java/org/apache/sling/auth/saml2/impl/AbstractSamlHandler.java
+++ b/saml-handler/src/main/java/org/apache/sling/auth/saml2/impl/AbstractSamlHandler.java
@@ -23,6 +23,9 @@
 import org.apache.sling.auth.core.spi.DefaultAuthenticationFeedbackHandler;
 import org.apache.sling.auth.saml2.AuthenticationHandlerSAML2Config;
 
+import java.util.HashMap;
+import java.util.Map;
+
 abstract class AbstractSamlHandler extends DefaultAuthenticationFeedbackHandler {
 
     // OSGI Configs
@@ -43,6 +46,7 @@
     private String acsPath;
     private String[] syncAttrs;
     private String saml2LogoutURL;
+    private Map syncAttrMap;
 
     public static final String GOTO_URL_SESSION_ATTRIBUTE = "gotoURL";
     public static final String SAML2_REQUEST_ID = "saml2RequestID";
@@ -66,6 +70,7 @@
         this.acsPath = config.acsPath();
         this.syncAttrs = config.syncAttrs();
         this.saml2LogoutURL = config.saml2LogoutURL();
+        setSyncMap();
     }
 
 //    GETTERS
@@ -120,11 +125,20 @@
     String[] getSyncAttrs() {
         return this.syncAttrs;
     }
+    Map<String,String> getSyncAttrMap(){ return this.syncAttrMap; }
 
     String getACSURL() {
         final String domain = entityID.endsWith("/") ? entityID.substring(0, entityID.length()-1) : entityID;
         return domain + this.getAcsPath();
     }
 
-
+    void setSyncMap(){
+        this.syncAttrMap = new HashMap<>();
+        for(String attr : getSyncAttrs()){
+            String[] parts = attr.split("=");
+            if(parts != null && parts.length==2){
+                this.syncAttrMap.put(parts[0],parts[1]);
+            }
+        }
+    }
 }
diff --git a/saml-handler/src/main/java/org/apache/sling/auth/saml2/impl/AuthenticationHandlerSAML2Impl.java b/saml-handler/src/main/java/org/apache/sling/auth/saml2/impl/AuthenticationHandlerSAML2Impl.java
index fb0a11a..0e5a288 100644
--- a/saml-handler/src/main/java/org/apache/sling/auth/saml2/impl/AuthenticationHandlerSAML2Impl.java
+++ b/saml-handler/src/main/java/org/apache/sling/auth/saml2/impl/AuthenticationHandlerSAML2Impl.java
@@ -478,20 +478,14 @@
         // start a user object
         Saml2User saml2User = new Saml2User();
 
-        // get list of configured attribute names to synchronize from the IDP assertion to the user's properties
-        List<String> attrNamesToSync = null;
-        if (this.getSyncAttrs() != null && this.getSyncAttrs().length > 0) {
-            attrNamesToSync = Arrays.asList(this.getSyncAttrs());
-        }
-
         // iterate the attribute assertions
         for (Attribute attribute : assertion.getAttributeStatements().get(0).getAttributes()) {
             if (attribute.getName().equals(this.getSaml2userIDAttr())) {
                 setUserId(attribute, saml2User);
             } else if (attribute.getName().equals(this.getSaml2groupMembershipAttr())) {
                 setGroupMembership(attribute, saml2User);
-            } else if (attrNamesToSync != null && attrNamesToSync.contains(attribute.getName())) {
-                syncUserAttributes(attribute, saml2User);
+            } else if (this.getSyncAttrMap() != null && this.getSyncAttrMap().containsKey(attribute.getName())){
+                syncUserAttributes(attribute, saml2User, this.getSyncAttrMap().get(attribute.getName()));
             }
         }
 
@@ -535,16 +529,12 @@
         }
     }
 
-    private void syncUserAttributes(Attribute attribute, Saml2User saml2User) {
+    private void syncUserAttributes(Attribute attribute, Saml2User saml2User, String propertyName) {
         for (XMLObject attributeValue : attribute.getAttributeValues()) {
-            if ( ((XSString) attributeValue).getValue() != null ) {
-                if (attribute.getFriendlyName() != null && !attribute.getFriendlyName().isEmpty()) {
-                    saml2User.addUserProperty(attribute.getFriendlyName(), attributeValue);
-                    logger.debug("sync attr name: {0}", attribute.getFriendlyName());
-                    logger.debug("attribute value: {0}", ((XSString) attributeValue).getValue());
-                } else {
-                    logger.warn("attribute has no friendly name and cannot be added: {0}", ((XSString) attributeValue).getValue());
-                }
+            if (((XSString) attributeValue).getValue() != null ) {
+                saml2User.addUserProperty(propertyName, attributeValue);
+                logger.debug("sync attr name: {0}", propertyName);
+                logger.debug("attribute value: {0}", ((XSString) attributeValue).getValue());
             }
         }
     }
diff --git a/saml-handler/src/main/java/org/apache/sling/auth/saml2/impl/Saml2UserMgtServiceImpl.java b/saml-handler/src/main/java/org/apache/sling/auth/saml2/impl/Saml2UserMgtServiceImpl.java
index 51b4db5..c9ec1e8 100644
--- a/saml-handler/src/main/java/org/apache/sling/auth/saml2/impl/Saml2UserMgtServiceImpl.java
+++ b/saml-handler/src/main/java/org/apache/sling/auth/saml2/impl/Saml2UserMgtServiceImpl.java
@@ -163,7 +163,7 @@
         try {
             User jcrUser = (User) this.userManager.getAuthorizable(user.getId());
             for (Map.Entry<String,String> entry : user.getUserProperties().entrySet()) {
-                jcrUser.setProperty("./profile/"+entry.getKey(), vf.createValue(entry.getValue()));
+                jcrUser.setProperty(entry.getKey(), vf.createValue(entry.getValue()));
             }
             session.save();
             return true;
diff --git a/saml-handler/src/test/java/org/apache/sling/auth/saml2/SamlHandlerIT.java b/saml-handler/src/test/java/org/apache/sling/auth/saml2/SamlHandlerIT.java
index 32c705d..18fa9cc 100644
--- a/saml-handler/src/test/java/org/apache/sling/auth/saml2/SamlHandlerIT.java
+++ b/saml-handler/src/test/java/org/apache/sling/auth/saml2/SamlHandlerIT.java
@@ -19,7 +19,6 @@
 
 package org.apache.sling.auth.saml2;
 
-import com.google.common.collect.Iterators;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.jackrabbit.api.JackrabbitSession;
 import org.apache.jackrabbit.api.security.user.Authorizable;
@@ -68,7 +67,6 @@
 import java.util.Base64;
 import java.util.Iterator;
 import java.util.List;
-
 import static org.apache.sling.auth.core.spi.AuthenticationHandler.REQUEST_LOGIN_PARAMETER;
 import static org.apache.sling.auth.saml2.impl.JKSHelper.IDP_ALIAS;
 import static org.apache.sling.auth.saml2.impl.JKSHelper.SP_ALIAS;
@@ -200,10 +198,10 @@
                 .asOption(),
             // supply the required configuration so the auth handler service will activate
             testBundle("bundle.filename"), // from TestSupport
-//                urn:oid:1.2.840.113549.1.9.1 = email
-//                urn:oid:2.5.4.4 = surname
-//                urn:oid:2.5.4.42 = givenName
-//                phone is configured but not included
+//                urn:oid:1.2.840.113549.1.9.1=profile/email
+//                urn:oid:2.5.4.4=profile/surname
+//                urn:oid:2.5.4.42=profile/givenName
+//                phone=profile/phone is configured but not included in assertion
             factoryConfiguration("org.apache.sling.auth.saml2.AuthenticationHandlerSAML2")
                 .put("path", "/")
                 .put("entityID", "http://localhost:8080/")
@@ -211,7 +209,7 @@
                 .put("saml2userIDAttr", "urn:oid:0.9.2342.19200300.100.1.1")
                 .put("saml2userHome", "/home/users/saml")
                 .put("saml2groupMembershipAttr", "urn:oid:2.16.840.1.113719.1.1.4.1.25")
-                .put("syncAttrs", new String[]{"urn:oid:2.5.4.4","urn:oid:2.5.4.42","phone","urn:oid:1.2.840.113549.1.9.1"})
+                .put("syncAttrs", new String[]{"urn:oid:2.5.4.4=./profile/surname","urn:oid:2.5.4.42=./profile/givenName","phone=./profile/phone","urn:oid:1.2.840.113549.1.9.1=./profile/email"})
                 .put("saml2SPEnabled", true)
                 .put("saml2SPEncryptAndSign", false)
                 .put("jksFileLocation", "")