Index: ../oak/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/PrincipalNameResolver.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- ../oak/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/PrincipalNameResolver.java	(revision )
+++ ../oak/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/PrincipalNameResolver.java	(revision )
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.jackrabbit.oak.spi.security.authentication.external;
+
+import javax.annotation.Nonnull;
+
+/**
+ * PrincipalNameResolver... TODO
+ */
+public interface PrincipalNameResolver {
+
+    @Nonnull
+    String fromExternalIdentityRef(@Nonnull ExternalIdentityRef externalIdentityRef) throws ExternalIdentityException;
+}
\ No newline at end of file
Index: ../oak/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/PrincipalResolutionTest.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- ../oak/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/PrincipalResolutionTest.java	(revision )
+++ ../oak/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/PrincipalResolutionTest.java	(revision )
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.jackrabbit.oak.spi.security.authentication.external.impl;
+
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentity;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityException;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProvider;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityRef;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.PrincipalNameResolver;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.TestIdentityProvider;
+
+public class PrincipalResolutionTest extends DynamicSyncContextTest {
+
+    @Override
+    protected ExternalIdentityProvider createIDP() {
+        return new PrincipalResolvingIDP();
+    }
+
+    // TODO: add more specific tests for the principal-name-resolution
+
+    private final class PrincipalResolvingIDP extends TestIdentityProvider implements PrincipalNameResolver {
+
+        @Nonnull
+        @Override
+        public String fromExternalIdentityRef(@Nonnull ExternalIdentityRef externalIdentityRef) throws ExternalIdentityException {
+            ExternalIdentity identity = getIdentity(externalIdentityRef);
+            if (identity == null) {
+                throw new ExternalIdentityException();
+            } else {
+                return identity.getPrincipalName();
+            }
+        }
+    }
+}
\ No newline at end of file
Index: ../oak/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DynamicSyncContext.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- ../oak/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DynamicSyncContext.java	(revision 1778156)
+++ ../oak/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DynamicSyncContext.java	(revision )
@@ -32,6 +32,7 @@
 import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProvider;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityRef;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalUser;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.PrincipalNameResolver;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncException;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncResult;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.basic.DefaultSyncConfig;
@@ -150,17 +151,22 @@
      * @throws ExternalIdentityException If an error occurs while resolving the the external group references.
      */
     private void collectPrincipalNames(@Nonnull Set<String> principalNames, @Nonnull Iterable<ExternalIdentityRef> declaredGroupIdRefs, long depth) throws ExternalIdentityException {
+        boolean shortcut = (depth <= 1 && idp instanceof PrincipalNameResolver);
         for (ExternalIdentityRef ref : declaredGroupIdRefs) {
-            // get group
+            if (shortcut) {
+                principalNames.add(((PrincipalNameResolver) idp).fromExternalIdentityRef(ref));
+            } else {
+                // get group from the IDP
-            ExternalIdentity extId = idp.getIdentity(ref);
-            if (extId instanceof ExternalGroup) {
-                principalNames.add(extId.getPrincipalName());
-                // recursively apply further membership until the configured depth is reached
-                if (depth > 1) {
-                    collectPrincipalNames(principalNames, extId.getDeclaredGroups(), depth - 1);
-                }
-            } else {
-                log.debug("Not an external group ({}) => ignore.", extId);
+                ExternalIdentity extId = idp.getIdentity(ref);
+                if (extId instanceof ExternalGroup) {
+                    principalNames.add(extId.getPrincipalName());
+                    // recursively apply further membership until the configured depth is reached
+                    if (depth > 1) {
+                        collectPrincipalNames(principalNames, extId.getDeclaredGroups(), depth - 1);
+                    }
+                } else {
+                    log.debug("Not an external group ({}) => ignore.", extId);
+                }
             }
         }
     }
\ No newline at end of file
Index: ../oak/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/package-info.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- ../oak/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/package-info.java	(revision 1778156)
+++ ../oak/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/package-info.java	(revision )
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-@Version("2.2.0")
+@Version("2.3.0")
 @Export
 package org.apache.jackrabbit.oak.spi.security.authentication.external;
 
\ No newline at end of file
Index: ../oak/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapProviderTest.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- ../oak/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapProviderTest.java	(revision 1778156)
+++ ../oak/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapProviderTest.java	(revision )
@@ -34,6 +34,7 @@
 import org.apache.jackrabbit.oak.security.authentication.ldap.impl.LdapProviderConfig;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalGroup;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentity;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityException;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityRef;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalUser;
 import org.apache.jackrabbit.util.Text;
@@ -406,6 +407,26 @@
         assertEquals("Intermediate path must be the split dn", TEST_USER5_PATH, user.getIntermediatePath());
     }
 
+    @Test
+    public void testResolvePrincipalNameUser() throws ExternalIdentityException {
+        ExternalUser user = idp.getUser(TEST_USER5_UID);
+        assertNotNull(user);
+
+        assertEquals(user.getPrincipalName(), idp.fromExternalIdentityRef(user.getExternalId()));
+    }
+
+    @Test
+    public void testResolvePrincipalNameGroup() throws ExternalIdentityException {
+        ExternalGroup gr = idp.getGroup(TEST_GROUP1_NAME);
+        assertNotNull(gr);
+
+        assertEquals(gr.getPrincipalName(), idp.fromExternalIdentityRef(gr.getExternalId()));
+    }
+
+    @Test(expected = ExternalIdentityException.class)
+    public void testResolvePrincipalNameForeignExtId() throws Exception {
+        idp.fromExternalIdentityRef(new ExternalIdentityRef("anyId", "anotherProviderName"));
+    }
 
     public static void assertIfEquals(String message, String[] expected, Iterable<ExternalIdentityRef> result) {
         List<String> dns = new LinkedList<String>();
Index: ../oak/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentityProvider.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- ../oak/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentityProvider.java	(revision 1778156)
+++ ../oak/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentityProvider.java	(revision )
@@ -78,6 +78,7 @@
 import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProvider;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityRef;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalUser;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.PrincipalNameResolver;
 import org.apache.jackrabbit.util.Text;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -93,7 +94,7 @@
         policy = ConfigurationPolicy.REQUIRE
 )
 @Service
-public class LdapIdentityProvider implements ExternalIdentityProvider {
+public class LdapIdentityProvider implements ExternalIdentityProvider, PrincipalNameResolver {
 
     /**
      * default logger
@@ -183,6 +184,15 @@
         }
     }
 
+    //----------------------------------------------< PrincipalNameResolver >---
+    @Nonnull
+    @Override
+    public String fromExternalIdentityRef(@Nonnull ExternalIdentityRef externalIdentityRef) throws ExternalIdentityException {
+        if (!isMyRef(externalIdentityRef)) {
+            throw new ExternalIdentityException("Foreign IDP " + externalIdentityRef.getString());
+        }
+        return externalIdentityRef.getId();
+    }
 
     //-------------------------------------------< ExternalIdentityProvider >---
     @Nonnull
\ No newline at end of file
