You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by dj...@apache.org on 2016/08/18 13:15:23 UTC

svn commit: r1756777 [1/4] - in /jackrabbit/oak/branches/1.2: ./ oak-auth-external/ oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/ oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/secu...

Author: dj
Date: Thu Aug 18 13:15:22 2016
New Revision: 1756777

URL: http://svn.apache.org/viewvc?rev=1756777&view=rev
Log:
OAK-4679 : Backport OAK-4119, OAK-4101, OAK-4087 and OAK-4344
- backported OAK-4101

Added:
    jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DynamicSyncContext.java
      - copied unchanged from r1744292, jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DynamicSyncContext.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalIdentityConstants.java
      - copied unchanged from r1744292, jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalIdentityConstants.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/
      - copied from r1744292, jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/
    jackrabbit/oak/branches/1.2/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/AbstractExternalAuthTest.java
      - copied, changed from r1740114, jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/AbstractExternalAuthTest.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleDynamicMembershipTest.java
      - copied unchanged from r1744292, jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleDynamicMembershipTest.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestSecurityProvider.java
      - copied, changed from r1744292, jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestSecurityProvider.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/
      - copied from r1711209, jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/
    jackrabbit/oak/branches/1.2/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncConfigTest.java
      - copied unchanged from r1740114, jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncConfigTest.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncResultImplTest.java
      - copied unchanged from r1740114, jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncResultImplTest.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncedIdentityTest.java
      - copied unchanged from r1740114, jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncedIdentityTest.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/RepExternalIdTest.java
      - copied unchanged from r1740114, jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/RepExternalIdTest.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/
    jackrabbit/oak/branches/1.2/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/CustomCredentialsSupportTest.java
      - copied, changed from r1735141, jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/CustomCredentialsSupportTest.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandlerTest.java
      - copied, changed from r1739712, jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandlerTest.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DynamicSyncContextTest.java
      - copied, changed from r1744292, jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DynamicSyncContextTest.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/
      - copied from r1744292, jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/
    jackrabbit/oak/branches/1.2/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/LongUtils.java
      - copied unchanged from r1685834, jackrabbit/oak/trunk/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/LongUtils.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/CacheConstants.java
      - copied unchanged from r1695223, jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/CacheConstants.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/CacheValidatorProvider.java
      - copied unchanged from r1695223, jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/CacheValidatorProvider.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/credentials/
      - copied from r1735141, jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/credentials/
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/CacheValidatorProviderTest.java
      - copied unchanged from r1695223, jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/CacheValidatorProviderTest.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserPrincipalProviderWithCacheTest.java
      - copied unchanged from r1695223, jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserPrincipalProviderWithCacheTest.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/credentials/
      - copied from r1735141, jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/credentials/
    jackrabbit/oak/branches/1.2/oak-doc/src/site/markdown/security/authentication/defaultusersync.md
      - copied, changed from r1740250, jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/authentication/defaultusersync.md
    jackrabbit/oak/branches/1.2/oak-doc/src/site/markdown/security/principal/cache.md
      - copied unchanged from r1695223, jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/principal/cache.md
    jackrabbit/oak/branches/1.2/oak-doc/src/site/markdown/security/principal/principalprovider.md
      - copied, changed from r1695223, jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/principal/principalprovider.md
    jackrabbit/oak/branches/1.2/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportCacheTest.java
      - copied unchanged from r1695223, jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportCacheTest.java
    jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/
      - copied from r1743674, jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/
Removed:
    jackrabbit/oak/branches/1.2/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/DefaultSyncHandlerTest.java
Modified:
    jackrabbit/oak/branches/1.2/   (props changed)
    jackrabbit/oak/branches/1.2/oak-auth-external/pom.xml
    jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncConfig.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncContext.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncResultImpl.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/package-info.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncConfigImpl.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandler.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalProvider.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTestBase.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestIdentityProvider.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncContextTest.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalIdentityImporterTest.java
    jackrabbit/oak/branches/1.2/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalPrincipalConfigurationTest.java
    jackrabbit/oak/branches/1.2/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginTestBase.java
    jackrabbit/oak/branches/1.2/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/PathUtils.java
    jackrabbit/oak/branches/1.2/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/package-info.java
    jackrabbit/oak/branches/1.2/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/PathUtilsTest.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypePredicate.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/package-info.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionEntryProviderImpl.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AbstractGroupPrincipal.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserConfigurationImpl.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImporter.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserPrincipalProvider.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/CompositeConfiguration.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/util/NodeUtil.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/util/package-info.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/resources/org/apache/jackrabbit/oak/plugins/nodetype/write/builtin_nodetypes.cnd
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserConfigurationImplTest.java
    jackrabbit/oak/branches/1.2/oak-doc/src/site/markdown/security/authentication.md
    jackrabbit/oak/branches/1.2/oak-doc/src/site/markdown/security/authentication/externalloginmodule.md
    jackrabbit/oak/branches/1.2/oak-doc/src/site/markdown/security/authentication/usersync.md
    jackrabbit/oak/branches/1.2/oak-doc/src/site/markdown/security/principal.md
    jackrabbit/oak/branches/1.2/oak-doc/src/site/markdown/security/user.md
    jackrabbit/oak/branches/1.2/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/ImporterImpl.java
    jackrabbit/oak/branches/1.2/oak-parent/pom.xml
    jackrabbit/oak/branches/1.2/oak-run/pom.xml
    jackrabbit/oak/branches/1.2/oak-run/run_concurrent_login.sh
    jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractLoginTest.java
    jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractTest.java
    jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java
    jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/LoginWithMembersTest.java
    jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/LoginWithMembershipTest.java
    jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/AbstractExternalTest.java

Propchange: jackrabbit/oak/branches/1.2/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Aug 18 13:15:22 2016
@@ -1,4 +1,4 @@
 /jackrabbit/oak/branches/1.0:1665962
 /jackrabbit/oak/branches/1.4:1745750,1747354,1750078,1750512
-/jackrabbit/oak/trunk:1672350,1672468-1672469,1672537,1672603,1672611,1672642,1672644,1672834-1672835,1673351,1673410,1673414-1673415,1673436,1673644,1673662-1673664,1673669,1673695,1673713,1673738,1673787,1673791,1674046,1674065,1674075,1674107,1674228,1674780,1674880,1675054-1675055,1675089,1675319,1675332,1675354,1675357,1675382,1675555,1675566,1675593,1676198,1676237,1676407,1676458,1676539,1676670,1676693,1676703,1676725,1677579,1677581,1677609,1677611,1677774,1677788,1677797,1677804,1677806,1677939,1677991,1678023,1678095-1678096,1678124,1678171,1678173,1678202,1678211,1678323,1678758,1678938,1678954,1679144,1679165,1679191,1679232,1679235,1679503,1679958,1679961,1680170,1680172,1680182,1680222,1680232,1680236,1680461,1680633,1680643,1680747,1680805-1680806,1680903,1681282,1681767,1681918,1681921,1681955,1682042,1682218,1682235,1682437,1682488,1682494,1682555,1682855,1682904,1683059,1683089,1683213,1683249,1683259,1683278,1683323,1683687,1683700,1684174-1684175,1684186,1684376
 ,1684442,1684561,1684570,1684601,1684618,1684669,1684820,1684868,1684894,1685023,1685075,1685370,1685541,1685552,1685589-1685590,1685839-1685840,1685964,1685977,1685989,1685999,1686003,1686023,1686032,1686097,1686162,1686229,1686234,1686253,1686414,1686772,1686780,1686790,1686854,1686857,1686971,1687053-1687055,1687175,1687196,1687198,1687220,1687239-1687240,1687301,1687441,1687553,1688089-1688090,1688172,1688179,1688349,1688421,1688436,1688453,1688616,1688622,1688634,1688636,1688817,1689003-1689004,1689008,1689577,1689581,1689623,1689810,1689828,1689831,1689833,1689903,1690017,1690043,1690047,1690057,1690247,1690249,1690634-1690637,1690650,1690657,1690669,1690672,1690674,1690885,1690941,1691139,1691151,1691159,1691167,1691183,1691188,1691201,1691210,1691217-1691218,1691280,1691307,1691331-1691333,1691345,1691384-1691385,1691394,1691401,1691498,1691509,1692133-1692134,1692156,1692250,1692272,1692274,1692363,1692382,1692393,1692478,1692955,1693002,1693030,1693050,1693209,1693401,1693
 421,1693525-1693526,1694007,1694049,1694393-1694394,1694651,1694653-1694654,1695032,1695050,1695122,1695280,1695299,1695420,1695457,1695482,1695492,1695507,1695521,1695540,1695571,1695829-1695830,1695905,1696190,1696194,1696242,1696285,1696375,1696522,1696578,1696759,1696916,1697363,1697373,1697383,1697410,1697582,1697589,1697616,1697672,1697896,1698096,1698144,1700191,1700231,1700397,1700403,1700506,1700571,1700709,1700718,1700720,1700727,1700749,1700769,1700775,1701065,1701613,1701619,1701733,1701743,1701750,1701768,1701806,1701810,1701814,1701907,1701948,1701955,1701959,1701965,1701986,1702014,1702022,1702045,1702051,1702241,1702272,1702371,1702387,1702405,1702423,1702426,1702428,1702860,1702866,1702942,1702960,1703212,1703382,1703395,1703411,1703428,1703430,1703568,1703592,1703758,1703858,1703878,1704256,1704282,1704285,1704457,1704479,1704490,1704614,1704629,1704636,1704655,1704670,1704886,1705005,1705027,1705043,1705055,1705250,1705268,1705273,1705323,1705677,1705701,1705871,1
 705992,1705998,1706009,1706037,1706059,1706212,1706218,1706270,1706764,1706772,1707049,1707189,1707191,1707331,1707435,1707509,1707753,1708049,1708105,1708307,1708315,1708401,1708546,1708592,1708766,1709012,1709852,1709978,1710013,1710031,1710049,1710205,1710242,1710559,1710575,1710590,1710614,1710637,1710789,1710800,1710811,1710816,1710972,1711248,1711282,1711296,1711405,1711498,1711654,1712018,1712042,1712319,1712490,1712531,1712730,1712785,1712963,1713008,1713439,1713461,1713580,1713586,1713599-1713600,1713626,1713698,1713803,1713809,1714034,1714061,1714084,1714170,1714213,1714229,1714238,1714519-1714520,1714543-1714544,1714730,1714739,1714779,1714956,1714961,1715010,1715092,1715191,1715346,1715716,1715767,1715771,1715888,1715898,1716100,1716178,1716426,1716576,1716588-1716589,1716596,1716616,1716703,1716712,1716815,1716823,1716830,1716883,1717203,1717277,1717393-1717394,1717410,1717462,1717632,1717768-1717769,1717784,1717789,1717988,1718528,1718533,1718546-1718548,1718553,171862
 6,1718646,1718772,1718801-1718802,1718895,1719111,1719288,1719869,1720306,1720335,1720350,1720354,1720500,1721160,1721172,1721337,1722141,1722832,1723227,1723239,1723241,1723251,1723254,1723333,1723347,1723350,1723565,1723584,1723713,1723731,1724026,1724057,1724186,1724210,1724401,1724628,1724631,1725216,1725477,1725515,1725555,1725895,1725899,1725935,1725941,1725960,1726232,1726237,1726570,1726579,1726585-1726586,1726621,1726795,1726797,1726809,1726812,1726981,1726993,1727026,1727254,1727331,1727350,1727358,1727429,1727476,1727483,1727508,1727515-1727518,1727813,1727816,1727831-1727832,1727841,1727893,1727895,1727912-1727913,1727923,1727991,1728037,1728041,1728070,1728114,1728281,1728443,1728525,1728642,1729200,1729505,1729599,1729957,1729979,1730216,1730527,1730581,1730629,1730801,1731627,1731647-1731648,1731789,1731797,1732131,1732268,1732278,1732330,1732647-1732648,1732864,1733615,1733929,1734230,1734254,1735052,1735267,1735405,1735484,1735564,1735588,1736176,1737309-1737310,173
 7334,1737349,1738138,1738252,1738833,1738950,1738957,1739894,1740116,1740626,1740971,1741032,1741339,1741343,1742520,1742888,1742916,1743097,1743172,1743343,1744265,1744959,1745038,1745197,1746117,1746696,1746981,1747341-1747342,1747492,1748505,1748553,1748722,1748870,1749350,1749464,1749475,1749645,1749662,1749815,1749872,1749875,1749899,1750052,1750076-1750077,1750287,1750457,1750462,1750465,1750495,1750626,1750809,1750886,1751410,1751445-1751446,1751478,1751755,1752198,1752202,1752273-1752274,1752438,1752508,1752659,1752672,1753262,1753331-1753332,1753355,1753444,1754117,1754239,1755366,1756520,1756580
+/jackrabbit/oak/trunk:1672350,1672468-1672469,1672537,1672603,1672611,1672642,1672644,1672834-1672835,1673351,1673410,1673414-1673415,1673436,1673644,1673662-1673664,1673669,1673695,1673713,1673738,1673787,1673791,1674046,1674065,1674075,1674107,1674228,1674780,1674880,1675054-1675055,1675089,1675319,1675332,1675354,1675357,1675382,1675555,1675566,1675593,1676198,1676237,1676407,1676458,1676539,1676670,1676693,1676703,1676725,1677579,1677581,1677609,1677611,1677774,1677788,1677797,1677804,1677806,1677939,1677991,1678023,1678095-1678096,1678124,1678171,1678173,1678202,1678211,1678323,1678758,1678938,1678954,1679144,1679165,1679191,1679232,1679235,1679503,1679958,1679961,1680170,1680172,1680182,1680222,1680232,1680236,1680461,1680633,1680643,1680747,1680805-1680806,1680903,1681282,1681767,1681918,1681921,1681955,1682042,1682218,1682235,1682437,1682488,1682494,1682555,1682855,1682904,1683059,1683089,1683213,1683249,1683259,1683278,1683323,1683687,1683700,1684174-1684175,1684186,1684376
 ,1684442,1684561,1684570,1684601,1684618,1684669,1684820,1684868,1684894,1685023,1685075,1685370,1685541,1685552,1685589-1685590,1685834,1685839-1685840,1685964,1685977,1685989,1685999,1686003,1686023,1686032,1686097,1686162,1686229,1686234,1686253,1686414,1686772,1686780,1686790,1686854,1686857,1686971,1687053-1687055,1687175,1687196,1687198,1687220,1687239-1687240,1687301,1687441,1687553,1688089-1688090,1688172,1688179,1688349,1688421,1688436,1688453,1688616,1688622,1688634,1688636,1688817,1689003-1689004,1689008,1689577,1689581,1689623,1689810,1689828,1689831,1689833,1689903,1690017,1690043,1690047,1690057,1690247,1690249,1690634-1690637,1690650,1690657,1690669,1690672,1690674,1690885,1690941,1691139,1691151,1691159,1691167,1691183,1691188,1691201,1691210,1691217-1691218,1691280,1691307,1691331-1691333,1691345,1691384-1691385,1691394,1691401,1691498,1691509,1692133-1692134,1692156,1692250,1692272,1692274,1692363,1692382,1692393,1692478,1692955,1693002,1693030,1693050,1693209,1693
 401,1693421,1693525-1693526,1694007,1694049,1694393-1694394,1694651,1694653-1694654,1695032,1695050,1695122,1695223,1695280,1695299,1695420,1695457,1695482,1695492,1695507,1695521,1695540,1695571,1695829-1695830,1695905,1696190,1696194,1696242,1696285,1696375,1696522,1696578,1696759,1696916,1697363,1697373,1697383,1697410,1697582,1697589,1697616,1697672,1697896,1698096,1698144,1700191,1700231,1700397,1700403,1700506,1700571,1700709,1700718,1700720,1700727,1700749,1700769,1700775,1701065,1701613,1701619,1701733,1701743,1701750,1701768,1701806,1701810,1701814,1701907,1701948,1701955,1701959,1701965,1701986,1702014,1702022,1702045,1702051,1702241,1702272,1702371,1702387,1702405,1702423,1702426,1702428,1702860,1702866,1702942,1702960,1703212,1703382,1703395,1703411,1703428,1703430,1703568,1703592,1703758,1703858,1703878,1704256,1704282,1704285,1704457,1704479,1704490,1704614,1704629,1704636,1704655,1704670,1704886,1705005,1705027,1705043,1705055,1705250,1705268,1705273,1705323,1705677,1
 705701,1705871,1705992,1705998,1706009,1706037,1706059,1706212,1706218,1706270,1706764,1706772,1707049,1707189,1707191,1707331,1707435,1707509,1707753,1708049,1708105,1708307,1708315,1708401,1708546,1708592,1708738,1708766,1709012,1709852,1709978,1710013,1710031,1710049,1710205,1710242,1710559,1710575,1710590,1710614,1710637,1710789,1710800,1710811,1710816,1710972,1711209,1711248,1711282,1711296,1711405,1711498,1711654,1712018,1712042,1712319,1712490,1712531,1712730,1712785,1712963,1713008,1713439,1713461,1713580,1713586,1713599-1713600,1713626,1713698,1713803,1713809,1714034,1714061,1714084,1714170,1714174,1714213,1714229,1714238,1714519-1714520,1714543-1714544,1714730,1714739,1714779,1714956,1714961,1715010,1715092,1715191,1715346,1715716,1715767,1715771,1715888,1715898,1716100,1716178,1716426,1716576,1716588-1716589,1716596,1716616,1716703,1716712,1716815,1716823,1716830,1716883,1717203,1717277,1717393-1717394,1717410,1717462,1717632,1717768-1717769,1717784,1717789,1717988,171852
 8,1718533,1718546-1718548,1718553,1718626,1718646,1718772,1718801-1718802,1718895,1719111,1719288,1719869,1720306,1720335,1720350,1720354,1720500,1721160,1721172,1721337,1722141,1722832,1723227,1723239,1723241,1723251,1723254,1723333,1723347,1723350,1723565,1723584,1723713,1723731,1724026,1724057,1724186,1724210,1724401,1724628,1724631,1725216,1725477,1725515,1725555,1725895,1725899,1725935,1725941,1725960,1726232,1726237,1726570,1726579,1726585-1726586,1726621,1726795,1726797,1726809,1726812,1726981,1726993,1727026,1727254,1727331,1727350,1727358,1727429,1727476,1727483,1727508,1727515-1727518,1727813,1727816,1727831-1727832,1727841,1727893,1727895,1727912-1727913,1727923,1727991,1728037,1728041,1728070,1728114,1728281,1728443,1728525,1728642,1729200,1729505,1729578,1729599,1729957,1729962,1729979,1730050,1730216,1730527,1730581,1730629,1730801,1731627,1731647-1731648,1731789,1731797,1732131,1732268,1732278,1732330,1732647-1732648,1732864,1733615,1733929,1734230,1734254,1735052,173
 5081,1735141,1735267,1735405,1735484,1735564,1735588,1736176,1737309-1737310,1737334,1737349,1738138,1738252,1738833,1738950,1738957,1739712,1739760,1739867,1739894,1739959-1739960,1740114,1740116,1740250,1740333,1740360,1740626,1740774,1740837,1740971,1741016,1741032,1741339,1741343,1742117,1742520,1742888,1742916,1743097,1743172,1743343,1743674,1744265,1744292,1744959,1745038,1745197,1746117,1746696,1746981,1747341-1747342,1747492,1748505,1748553,1748722,1748870,1749350,1749464,1749475,1749645,1749662,1749815,1749872,1749875,1749899,1750052,1750076-1750077,1750287,1750457,1750462,1750465,1750495,1750626,1750809,1750886,1751410,1751445-1751446,1751478,1751755,1752198,1752202,1752273-1752274,1752438,1752508,1752659,1752672,1753262,1753331-1753332,1753355,1753444,1754117,1754239,1755366,1756520,1756580
 /jackrabbit/trunk:1345480

Modified: jackrabbit/oak/branches/1.2/oak-auth-external/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-auth-external/pom.xml?rev=1756777&r1=1756776&r2=1756777&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-auth-external/pom.xml (original)
+++ jackrabbit/oak/branches/1.2/oak-auth-external/pom.xml Thu Aug 18 13:15:22 2016
@@ -149,6 +149,12 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>oak-jcr</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <scope>test</scope>

Modified: jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncConfig.java?rev=1756777&r1=1756776&r2=1756777&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncConfig.java (original)
+++ jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncConfig.java Thu Aug 18 13:15:22 2016
@@ -50,6 +50,7 @@ public class DefaultSyncConfig {
      * @return {@code this}
      * @see #getName()
      */
+    @Nonnull
     public DefaultSyncConfig setName(@Nonnull String name) {
         this.name = name;
         return this;
@@ -117,16 +118,18 @@ public class DefaultSyncConfig {
         }
 
         /**
-         * Sets the auto membership
+         * Sets the auto membership. Note that the passed group names will be trimmed
+         * and empty string values will be ignored (along with {@code null} values).
+         *
          * @param autoMembership the membership
          * @return {@code this}
          * @see #getAutoMembership()
          */
         @Nonnull
-        public Authorizable setAutoMembership(String ... autoMembership) {
+        public Authorizable setAutoMembership(@Nonnull String ... autoMembership) {
             this.autoMembership = new HashSet<String>();
             for (String groupName: autoMembership) {
-                if (!groupName.trim().isEmpty()) {
+                if (groupName != null && !groupName.trim().isEmpty()) {
                     this.autoMembership.add(groupName.trim());
                 }
             }
@@ -164,7 +167,7 @@ public class DefaultSyncConfig {
          * @see #getPropertyMapping()
          */
         @Nonnull
-        public Authorizable setPropertyMapping(Map<String, String> propertyMapping) {
+        public Authorizable setPropertyMapping(@Nonnull Map<String, String> propertyMapping) {
             this.propertyMapping = propertyMapping;
             return this;
         }
@@ -186,7 +189,7 @@ public class DefaultSyncConfig {
          * @see #getPathPrefix()
          */
         @Nonnull
-        public Authorizable setPathPrefix(String pathPrefix) {
+        public Authorizable setPathPrefix(@Nonnull String pathPrefix) {
             this.pathPrefix = pathPrefix;
             return this;
         }
@@ -201,6 +204,8 @@ public class DefaultSyncConfig {
 
         private long membershipNestingDepth;
 
+        private boolean dynamicMembership;
+
         /**
          * Returns the duration in milliseconds until the group membership of a user is expired. If the
          * membership information is expired it is re-synced according to the maximum nesting depth.
@@ -248,6 +253,40 @@ public class DefaultSyncConfig {
             return this;
         }
 
+        /**
+         * Returns {@code true} if a dynamic group membership is enabled.
+         *
+         * Turning this option on may alter the behavior of other configuration
+         * options dealing with synchronization of group accounts and group membership.
+         * In particular it's an implementation detail if external groups may
+         * no longer be synchronized into the repository.
+         *
+         * @return {@code true} if dynamic group membership for external
+         * user identities is turn on; {@code false} otherwise.
+         */
+        @Nonnull
+        public boolean getDynamicMembership() {
+            return dynamicMembership;
+        }
+
+        /**
+         * Enable or disable the dynamic group membership. If turned external
+         * identities and their group membership will be synchronized such that the
+         * membership information is generated dynamically. External groups may
+         * or may not be synchronized into the repository if this option is turned
+         * on.
+         *
+         * @param dynamicMembership Boolean flag to enable or disable a dedicated
+         *                      dynamic group management.
+         * @return {@code this}
+         * @see #getDynamicMembership() for details.
+         */
+        @Nonnull
+        public User setDynamicMembership(boolean dynamicMembership) {
+            this.dynamicMembership = dynamicMembership;
+            return this;
+        }
+
     }
 
     /**

Modified: jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncContext.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncContext.java?rev=1756777&r1=1756776&r2=1756777&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncContext.java (original)
+++ jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncContext.java Thu Aug 18 13:15:22 2016
@@ -17,6 +17,7 @@
 package org.apache.jackrabbit.oak.spi.security.authentication.external.basic;
 
 import java.io.ByteArrayInputStream;
+import java.io.InputStream;
 import java.math.BigDecimal;
 import java.security.Principal;
 import java.util.ArrayList;
@@ -42,6 +43,7 @@ import org.apache.jackrabbit.api.securit
 import org.apache.jackrabbit.api.security.user.Group;
 import org.apache.jackrabbit.api.security.user.User;
 import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.oak.commons.PathUtils;
 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;
@@ -95,7 +97,7 @@ public class DefaultSyncContext implemen
 
     protected final Value nowValue;
 
-    public DefaultSyncContext(DefaultSyncConfig config, ExternalIdentityProvider idp, UserManager userManager, ValueFactory valueFactory) {
+    public DefaultSyncContext(@Nonnull DefaultSyncConfig config, @Nonnull ExternalIdentityProvider idp, @Nonnull UserManager userManager, @Nonnull ValueFactory valueFactory) {
         this.config = config;
         this.idp = idp;
         this.userManager = userManager;
@@ -149,28 +151,10 @@ public class DefaultSyncContext implemen
      * Robust relative path concatenation.
      * @param paths relative paths
      * @return the concatenated path
+     * @deprecated Since Oak 1.3.10. Please use {@link PathUtils#concatRelativePaths(String...)} instead.
      */
     public static String joinPaths(String... paths) {
-        StringBuilder result = new StringBuilder();
-        for (String path: paths) {
-            if (path != null && !path.isEmpty()) {
-                int i0 = 0;
-                int i1 = path.length();
-                while (i0 < i1 && path.charAt(i0) == '/') {
-                    i0++;
-                }
-                while (i1 > i0 && path.charAt(i1-1) == '/') {
-                    i1--;
-                }
-                if (i1 > i0) {
-                    if (result.length() > 0) {
-                        result.append('/');
-                    }
-                    result.append(path.substring(i0, i1));
-                }
-            }
-        }
-        return result.length() == 0 ? null : result.toString();
+        return PathUtils.concatRelativePaths(paths);
     }
 
     /**
@@ -225,6 +209,7 @@ public class DefaultSyncContext implemen
         return forceGroupSync;
     }
 
+    @Override
     @Nonnull
     public SyncContext setForceGroupSync(boolean forceGroupSync) {
         this.forceGroupSync = forceGroupSync;
@@ -237,6 +222,12 @@ public class DefaultSyncContext implemen
     @Nonnull
     @Override
     public SyncResult sync(@Nonnull ExternalIdentity identity) throws SyncException {
+        ExternalIdentityRef ref = identity.getExternalId();
+        if (!isSameIDP(ref)) {
+            // create result in accordance with sync(String) where status is FOREIGN
+            boolean isGroup = (identity instanceof ExternalGroup);
+            return new DefaultSyncResultImpl(new DefaultSyncedIdentity(identity.getId(), ref, isGroup, -1), SyncResult.Status.FOREIGN);
+        }
         try {
             DebugTimer timer = new DebugTimer();
             DefaultSyncResultImpl ret;
@@ -265,7 +256,7 @@ public class DefaultSyncContext implemen
                 throw new IllegalArgumentException("identity must be user or group but was: " + identity);
             }
             if (log.isDebugEnabled()) {
-                log.debug("sync({}) -> {} {}", identity.getExternalId().getString(), identity.getId(), timer.getString());
+                log.debug("sync({}) -> {} {}", ref.getString(), identity.getId(), timer.getString());
             }
             if (created) {
                 ret.setStatus(SyncResult.Status.ADD);
@@ -291,47 +282,25 @@ public class DefaultSyncContext implemen
                 return new DefaultSyncResultImpl(new DefaultSyncedIdentity(id, null, false, -1), SyncResult.Status.NO_SUCH_AUTHORIZABLE);
             }
             // check if we need to deal with this authorizable
-            ExternalIdentityRef ref = DefaultSyncContext.getIdentityRef(auth);
-            if (ref == null || !idp.getName().equals(ref.getProviderName())) {
-                return new DefaultSyncResultImpl(new DefaultSyncedIdentity(id, null, false, -1), SyncResult.Status.FOREIGN);
+            ExternalIdentityRef ref = getIdentityRef(auth);
+            if (ref == null || !isSameIDP(ref)) {
+                return new DefaultSyncResultImpl(new DefaultSyncedIdentity(id, ref, auth.isGroup(), -1), SyncResult.Status.FOREIGN);
             }
 
-            if (auth instanceof Group) {
-                Group group = (Group) auth;
+            if (auth.isGroup()) {
                 ExternalGroup external = idp.getGroup(id);
                 timer.mark("retrieve");
                 if (external == null) {
-                    DefaultSyncedIdentity syncId = DefaultSyncContext.createSyncedIdentity(auth);
-                    if (group.getDeclaredMembers().hasNext()) {
-                        log.info("won't remove local group with members: {}", id);
-                        ret = new DefaultSyncResultImpl(syncId, SyncResult.Status.NOP);
-                    } else if (!keepMissing) {
-                        auth.remove();
-                        log.debug("removing authorizable '{}' that no longer exists on IDP {}", id, idp.getName());
-                        timer.mark("remove");
-                        ret = new DefaultSyncResultImpl(syncId, SyncResult.Status.DELETE);
-                    } else {
-                        ret = new DefaultSyncResultImpl(syncId, SyncResult.Status.MISSING);
-                        log.info("external identity missing for {}, but purge == false.", id);
-                    }
+                    ret = handleMissingIdentity(id, auth, timer);
                 } else {
-                    ret = syncGroup(external, group);
+                    ret = syncGroup(external, (Group) auth);
                     timer.mark("sync");
                 }
             } else {
                 ExternalUser external = idp.getUser(id);
                 timer.mark("retrieve");
                 if (external == null) {
-                    DefaultSyncedIdentity syncId = DefaultSyncContext.createSyncedIdentity(auth);
-                    if (!keepMissing) {
-                        auth.remove();
-                        log.debug("removing authorizable '{}' that no longer exists on IDP {}", id, idp.getName());
-                        timer.mark("remove");
-                        ret = new DefaultSyncResultImpl(syncId, SyncResult.Status.DELETE);
-                    } else {
-                        ret = new DefaultSyncResultImpl(syncId, SyncResult.Status.MISSING);
-                        log.info("external identity missing for {}, but purge == false.", id);
-                    }
+                    ret = handleMissingIdentity(id, auth, timer);
                 } else {
                     ret = syncUser(external, (User) auth);
                     timer.mark("sync");
@@ -348,6 +317,26 @@ public class DefaultSyncContext implemen
         }
     }
 
+    private DefaultSyncResultImpl handleMissingIdentity(@Nonnull String id,
+                                                        @Nonnull Authorizable authorizable,
+                                                        @Nonnull DebugTimer timer) throws RepositoryException {
+        DefaultSyncedIdentity syncId = createSyncedIdentity(authorizable);
+        SyncResult.Status status;
+        if (authorizable.isGroup() && ((Group) authorizable).getDeclaredMembers().hasNext()) {
+            log.info("won't remove local group with members: {}", id);
+            status = SyncResult.Status.NOP;
+        } else if (!keepMissing) {
+            authorizable.remove();
+            log.debug("removing authorizable '{}' that no longer exists on IDP {}", id, idp.getName());
+            timer.mark("remove");
+            status = SyncResult.Status.DELETE;
+        } else {
+            status = SyncResult.Status.MISSING;
+            log.info("external identity missing for {}, but purge == false.", id);
+        }
+        return new DefaultSyncResultImpl(syncId, status);
+    }
+
     /**
      * Retrieves the repository authorizable that corresponds to the given external identity
      * @param external the external identity
@@ -357,7 +346,7 @@ public class DefaultSyncContext implemen
      * @throws SyncException if the repository contains a colliding authorizable with the same name.
      */
     @CheckForNull
-    protected <T extends Authorizable> T getAuthorizable(@Nonnull ExternalIdentity external, Class<T> type)
+    protected <T extends Authorizable> T getAuthorizable(@Nonnull ExternalIdentity external, @Nonnull Class<T> type)
             throws RepositoryException, SyncException {
         Authorizable authorizable = userManager.getAuthorizable(external.getId());
         if (authorizable == null) {
@@ -389,9 +378,9 @@ public class DefaultSyncContext implemen
                 externalUser.getId(),
                 null,
                 principal,
-                joinPaths(config.user().getPathPrefix(), externalUser.getIntermediatePath())
+                PathUtils.concatRelativePaths(config.user().getPathPrefix(), externalUser.getIntermediatePath())
         );
-        user.setProperty(REP_EXTERNAL_ID, valueFactory.createValue(externalUser.getExternalId().getString()));
+        setExternalId(user, externalUser);
         return user;
     }
 
@@ -409,55 +398,75 @@ public class DefaultSyncContext implemen
         Group group = userManager.createGroup(
                 externalGroup.getId(),
                 principal,
-                joinPaths(config.group().getPathPrefix(), externalGroup.getIntermediatePath())
+                PathUtils.concatRelativePaths(config.group().getPathPrefix(), externalGroup.getIntermediatePath())
         );
-        group.setProperty(REP_EXTERNAL_ID, valueFactory.createValue(externalGroup.getExternalId().getString()));
+        setExternalId(group, externalGroup);
         return group;
     }
 
+    /**
+     * Sets the {@link #REP_EXTERNAL_ID} as obtained from {@code externalIdentity}
+     * to the specified {@code authorizable} (user or group). The property is
+     * a single value of type {@link javax.jcr.PropertyType#STRING STRING}.
+     *
+     * @param authorizable The user or group that needs to get the {@link #REP_EXTERNAL_ID} property set.
+     * @param externalIdentity The {@link ExternalIdentity} from which to retrieve the value of the property.
+     * @throws RepositoryException If setting the property using {@link Authorizable#setProperty(String, Value)} fails.
+     */
+    private void setExternalId(@Nonnull Authorizable authorizable, @Nonnull ExternalIdentity externalIdentity) throws RepositoryException {
+        log.debug("Fallback: setting rep:externalId without adding the corresponding mixin type");
+        authorizable.setProperty(REP_EXTERNAL_ID, valueFactory.createValue(externalIdentity.getExternalId().getString()));
+    }
+
     @Nonnull
     protected DefaultSyncResultImpl syncUser(@Nonnull ExternalUser external, @Nonnull User user) throws RepositoryException {
+        SyncResult.Status status;
         // first check if user is expired
-        if (!forceUserSync && !isExpired(user, config.user().getExpirationTime(), "Properties")) {
-            DefaultSyncedIdentity syncId = DefaultSyncContext.createSyncedIdentity(user);
-            return new DefaultSyncResultImpl(syncId, SyncResult.Status.NOP);
-        }
-
-        // synchronize the properties
-        syncProperties(external, user, config.user().getPropertyMapping());
-
-        // synchronize auto-group membership
-        applyMembership(user, config.user().getAutoMembership());
-
-        if (isExpired(user, config.user().getMembershipExpirationTime(), "Membership")) {
-            // synchronize external memberships
-            syncMembership(external, user, config.user().getMembershipNestingDepth());
+        if (!forceUserSync && !isExpired(user)) {
+            status = SyncResult.Status.NOP;
+        } else {
+            syncExternalIdentity(external, user, config.user());
+            if (isExpired(user, config.user().getMembershipExpirationTime(), "Membership")) {
+                // synchronize external memberships
+                syncMembership(external, user, config.user().getMembershipNestingDepth());
+            }
+            // finally "touch" the sync property
+            user.setProperty(REP_LAST_SYNCED, nowValue);
+            status = SyncResult.Status.UPDATE;
         }
-
-        // finally "touch" the sync property
-        user.setProperty(REP_LAST_SYNCED, nowValue);
-        DefaultSyncedIdentity syncId = DefaultSyncContext.createSyncedIdentity(user);
-        return new DefaultSyncResultImpl(syncId, SyncResult.Status.UPDATE);
+        return new DefaultSyncResultImpl(createSyncedIdentity(user), status);
     }
 
     @Nonnull
     protected DefaultSyncResultImpl syncGroup(@Nonnull ExternalGroup external, @Nonnull Group group) throws RepositoryException {
-        // first check if user is expired
-        if (!forceGroupSync && !isExpired(group, config.group().getExpirationTime(), "Properties")) {
-            DefaultSyncedIdentity syncId = DefaultSyncContext.createSyncedIdentity(group);
-            return new DefaultSyncResultImpl(syncId, SyncResult.Status.NOP);
+        SyncResult.Status status;
+        // first check if group is expired
+        if (!forceGroupSync && !isExpired(group)) {
+            status = SyncResult.Status.NOP;
+        } else {
+            syncExternalIdentity(external, group, config.group());
+            // finally "touch" the sync property
+            group.setProperty(REP_LAST_SYNCED, nowValue);
+            status = SyncResult.Status.UPDATE;
         }
+        return new DefaultSyncResultImpl(createSyncedIdentity(group), status);
+    }
 
-        // synchronize the properties
-        syncProperties(external, group, config.group().getPropertyMapping());
-
-        // synchronize auto-group membership
-        applyMembership(group, config.group().getAutoMembership());
-
-        // finally "touch" the sync property
-        group.setProperty(REP_LAST_SYNCED, nowValue);
-        DefaultSyncedIdentity syncId = DefaultSyncContext.createSyncedIdentity(group);
-        return new DefaultSyncResultImpl(syncId, SyncResult.Status.UPDATE);
+    /**
+     * Synchronize content common to both external users and external groups:
+     * - properties
+     * - auto-group membership
+     *
+     * @param external The external identity
+     * @param authorizable The corresponding repository user/group
+     * @param config The sync configuration
+     * @throws RepositoryException If an error occurs.
+     */
+    private void syncExternalIdentity(@Nonnull ExternalIdentity external,
+                                      @Nonnull Authorizable authorizable,
+                                      @Nonnull DefaultSyncConfig.Authorizable config) throws RepositoryException {
+        syncProperties(external, authorizable, config.getPropertyMapping());
+        applyMembership(authorizable, config.getAutoMembership());
     }
 
     /**
@@ -469,7 +478,7 @@ public class DefaultSyncContext implemen
      * @param depth recursion depth.
      * @throws RepositoryException
      */
-    protected void syncMembership(ExternalIdentity external, Authorizable auth, long depth)
+    protected void syncMembership(@Nonnull ExternalIdentity external, @Nonnull Authorizable auth, long depth)
             throws RepositoryException {
         if (depth <= 0) {
             return;
@@ -504,35 +513,32 @@ public class DefaultSyncContext implemen
             // get group
             ExternalGroup extGroup;
             try {
-                extGroup = (ExternalGroup) idp.getIdentity(ref);
-            } catch (ClassCastException e) {
-                // this should really not be the case, so catching the CCE is ok here.
-                log.warn("External identity '{}' is not a group, but should be one.", ref.getString());
-                continue;
+                ExternalIdentity extId = idp.getIdentity(ref);
+                if (extId instanceof ExternalGroup) {
+                    extGroup = (ExternalGroup) extId;
+                } else {
+                    log.warn("No external group found for ref '{}'.", ref.getString());
+                    continue;
+                }
             } catch (ExternalIdentityException e) {
                 log.warn("Unable to retrieve external group '{}' from provider.", ref.getString(), e);
                 continue;
             }
-            if (extGroup == null) {
-                log.warn("External group for ref '{}' could not be retrieved from provider.", ref);
-                continue;
-            }
             log.debug("- idp returned '{}'", extGroup.getId());
 
             Group grp;
-            try {
-                grp = (Group) userManager.getAuthorizable(extGroup.getId());
-            } catch (ClassCastException e) {
-                // this should really not be the case, so catching the CCE is ok here.
+            Authorizable a = userManager.getAuthorizable(extGroup.getId());
+            if (a == null) {
+                grp = createGroup(extGroup);
+                log.debug("- created new group");
+            } else if (a.isGroup()) {
+                grp = (Group) a;
+            } else {
                 log.warn("Authorizable '{}' is not a group, but should be one.", extGroup.getId());
                 continue;
             }
             log.debug("- user manager returned '{}'", grp);
 
-            if (grp == null) {
-                grp = createGroup(extGroup);
-                log.debug("- created new group");
-            }
             syncGroup(extGroup, grp);
 
             // ensure membership
@@ -552,7 +558,7 @@ public class DefaultSyncContext implemen
         }
         timer.mark("adding");
         // remove us from the lost membership groups
-        for (Group grp: declaredExternalGroups.values()) {
+        for (Group grp : declaredExternalGroups.values()) {
             grp.removeMember(auth);
             log.debug("- removing member '{}' for group '{}'", auth.getID(), grp.getID());
         }
@@ -568,8 +574,8 @@ public class DefaultSyncContext implemen
      * @param member the authorizable
      * @param groups set of groups.
      */
-    protected void applyMembership(Authorizable member, Set<String> groups) throws RepositoryException {
-        for (String groupName: groups) {
+    protected void applyMembership(@Nonnull Authorizable member, @Nonnull Set<String> groups) throws RepositoryException {
+        for (String groupName : groups) {
             Authorizable group = userManager.getAuthorizable(groupName);
             if (group == null) {
                 log.warn("Unable to apply auto-membership to {}. No such group: {}", member.getID(), groupName);
@@ -590,10 +596,10 @@ public class DefaultSyncContext implemen
      * @param mapping the property mapping
      * @throws RepositoryException if an error occurs
      */
-    protected void syncProperties(ExternalIdentity ext, Authorizable auth, Map<String, String> mapping)
+    protected void syncProperties(@Nonnull ExternalIdentity ext, @Nonnull Authorizable auth, @Nonnull Map<String, String> mapping)
             throws RepositoryException {
         Map<String, ?> properties = ext.getProperties();
-        for (Map.Entry<String, String> entry: mapping.entrySet()) {
+        for (Map.Entry<String, String> entry : mapping.entrySet()) {
             String relPath = entry.getKey();
             String name = entry.getValue();
             Object obj = properties.get(name);
@@ -620,12 +626,23 @@ public class DefaultSyncContext implemen
 
     /**
      * Checks if the given authorizable needs syncing based on the {@link #REP_LAST_SYNCED} property.
+     *
+     * @param authorizable the authorizable to check
+     * @return {@code true} if the authorizable needs sync
+     */
+    private boolean isExpired(@Nonnull Authorizable authorizable) throws RepositoryException {
+        long expTime = (authorizable.isGroup()) ? config.group().getExpirationTime() : config.user().getExpirationTime();
+        return isExpired(authorizable, expTime, "Properties");
+    }
+
+    /**
+     * Checks if the given authorizable needs syncing based on the {@link #REP_LAST_SYNCED} property.
      * @param auth the authorizable to check
      * @param expirationTime the expiration time to compare to.
      * @param type debug message type
      * @return {@code true} if the authorizable needs sync
      */
-    protected boolean isExpired(Authorizable auth, long expirationTime, String type) throws RepositoryException {
+    protected boolean isExpired(@Nonnull Authorizable auth, long expirationTime, @Nonnull String type) throws RepositoryException {
         Value[] values = auth.getProperty(REP_LAST_SYNCED);
         if (values == null || values.length == 0) {
             if (log.isDebugEnabled()) {
@@ -674,6 +691,10 @@ public class DefaultSyncContext implemen
         } else if (v instanceof byte[]) {
             Binary bin = valueFactory.createBinary(new ByteArrayInputStream((byte[])v));
             return valueFactory.createValue(bin);
+        } else if (v instanceof Binary) {
+            return valueFactory.createValue((Binary) v);
+        } else if (v instanceof InputStream) {
+            return valueFactory.createValue((InputStream) v);
         } else if (v instanceof char[]) {
             return valueFactory.createValue(new String((char[]) v));
         } else {
@@ -688,7 +709,7 @@ public class DefaultSyncContext implemen
      * @throws RepositoryException if an error occurs
      */
     @CheckForNull
-    protected Value[] createValues(Collection<?> propValues) throws RepositoryException {
+    protected Value[] createValues(@Nonnull Collection<?> propValues) throws RepositoryException {
         List<Value> values = new ArrayList<Value>();
         for (Object obj : propValues) {
             Value v = createValue(obj);
@@ -709,7 +730,19 @@ public class DefaultSyncContext implemen
      * @return {@code true} if same IDP.
      */
     protected boolean isSameIDP(@Nullable Authorizable auth) throws RepositoryException {
-        ExternalIdentityRef ref = DefaultSyncContext.getIdentityRef(auth);
+        ExternalIdentityRef ref = getIdentityRef(auth);
         return ref != null && idp.getName().equals(ref.getProviderName());
     }
+
+    /**
+     * Tests if the given {@link ExternalIdentityRef} refers to the same IDP
+     * as associated with this context instance.
+     *
+     * @param ref The {@link ExternalIdentityRef} to be tested.
+     * @return {@code true} if {@link ExternalIdentityRef#getProviderName()} refers
+     * to the IDP associated with this context instance.
+     */
+    protected boolean isSameIDP(@Nonnull ExternalIdentityRef ref) {
+        return idp.getName().equals(ref.getProviderName());
+    }
 }
\ No newline at end of file

Modified: jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncResultImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncResultImpl.java?rev=1756777&r1=1756776&r2=1756777&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncResultImpl.java (original)
+++ jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncResultImpl.java Thu Aug 18 13:15:22 2016
@@ -18,6 +18,7 @@ package org.apache.jackrabbit.oak.spi.se
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncResult;
 
@@ -30,22 +31,24 @@ public class DefaultSyncResultImpl imple
 
     private Status status = Status.NOP;
 
-    public DefaultSyncResultImpl(DefaultSyncedIdentity id, Status status) {
+    public DefaultSyncResultImpl(@Nullable DefaultSyncedIdentity id, @Nonnull Status status) {
         this.id = id;
         this.status = status;
     }
 
+    @Override
     @CheckForNull
     public DefaultSyncedIdentity getIdentity() {
         return id;
     }
 
+    @Override
     @Nonnull
     public Status getStatus() {
         return status;
     }
 
-    public void setStatus(Status status) {
+    public void setStatus(@Nonnull Status status) {
         this.status = status;
     }
 }
\ No newline at end of file

Modified: jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/package-info.java?rev=1756777&r1=1756776&r2=1756777&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/package-info.java (original)
+++ jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/package-info.java Thu Aug 18 13:15:22 2016
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-@Version("1.0.0")
+@Version("1.1.0")
 @Export
 package org.apache.jackrabbit.oak.spi.security.authentication.external.basic;
 

Modified: jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncConfigImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncConfigImpl.java?rev=1756777&r1=1756776&r2=1756777&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncConfigImpl.java (original)
+++ jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncConfigImpl.java Thu Aug 18 13:15:22 2016
@@ -56,12 +56,12 @@ public class DefaultSyncConfigImpl exten
     public static final String PARAM_NAME = "handler.name";
 
     /**
-     * @see DefaultSyncConfigImpl.User#getExpirationTime()
+     * @see DefaultSyncConfig.User#getExpirationTime()
      */
     public static final String PARAM_USER_EXPIRATION_TIME_DEFAULT = "1h";
 
     /**
-     * @see DefaultSyncConfigImpl.User#getExpirationTime()
+     * @see DefaultSyncConfig.User#getExpirationTime()
      */
     @Property(
             label = "User Expiration Time",
@@ -71,12 +71,12 @@ public class DefaultSyncConfigImpl exten
     public static final String PARAM_USER_EXPIRATION_TIME = "user.expirationTime";
 
     /**
-     * @see DefaultSyncConfigImpl.User#getAutoMembership()
+     * @see DefaultSyncConfig.User#getAutoMembership()
      */
     public static final String[] PARAM_USER_AUTO_MEMBERSHIP_DEFAULT = {};
 
     /**
-     * @see DefaultSyncConfigImpl.User#getAutoMembership()
+     * @see DefaultSyncConfig.User#getAutoMembership()
      */
     @Property(
             label = "User auto membership",
@@ -87,12 +87,12 @@ public class DefaultSyncConfigImpl exten
     public static final String PARAM_USER_AUTO_MEMBERSHIP = "user.autoMembership";
 
     /**
-     * @see DefaultSyncConfigImpl.User#getPropertyMapping()
+     * @see DefaultSyncConfig.User#getPropertyMapping()
      */
     public static final String[] PARAM_USER_PROPERTY_MAPPING_DEFAULT = {"rep:fullname=cn"};
 
     /**
-     * @see DefaultSyncConfigImpl.User#getPropertyMapping()
+     * @see DefaultSyncConfig.User#getPropertyMapping()
      */
     @Property(
             label = "User property mapping",
@@ -104,12 +104,12 @@ public class DefaultSyncConfigImpl exten
     public static final String PARAM_USER_PROPERTY_MAPPING = "user.propertyMapping";
 
     /**
-     * @see DefaultSyncConfigImpl.User#getPathPrefix()
+     * @see DefaultSyncConfig.User#getPathPrefix()
      */
     public static final String PARAM_USER_PATH_PREFIX_DEFAULT = "";
 
     /**
-     * @see DefaultSyncConfigImpl.User#getPathPrefix()
+     * @see DefaultSyncConfig.User#getPathPrefix()
      */
     @Property(
             label = "User Path Prefix",
@@ -119,27 +119,27 @@ public class DefaultSyncConfigImpl exten
     public static final String PARAM_USER_PATH_PREFIX = "user.pathPrefix";
 
     /**
-     * @see DefaultSyncConfigImpl.User#getMembershipExpirationTime()
+     * @see DefaultSyncConfig.User#getMembershipExpirationTime()
      */
     public static final String PARAM_USER_MEMBERSHIP_EXPIRATION_TIME_DEFAULT = "1h";
 
     /**
-     * @see DefaultSyncConfigImpl.User#getMembershipExpirationTime()
+     * @see DefaultSyncConfig.User#getMembershipExpirationTime()
      */
     @Property(
             label = "User Membership Expiration",
-            description = "Time after which membership expires (eg. '1h 30m' or '1d').",
+            description = "Time after which membership expires (eg. '1h 30m' or '1d'). Note however, that a membership sync is aways bound to a sync of the user.",
             value = PARAM_USER_MEMBERSHIP_EXPIRATION_TIME_DEFAULT
     )
     public static final String PARAM_USER_MEMBERSHIP_EXPIRATION_TIME = "user.membershipExpTime";
 
     /**
-     * @see User#getMembershipNestingDepth()
+     * @see DefaultSyncConfig.User#getMembershipNestingDepth()
      */
     public static final int PARAM_USER_MEMBERSHIP_NESTING_DEPTH_DEFAULT = 0;
 
     /**
-     * @see User#getMembershipNestingDepth()
+     * @see DefaultSyncConfig.User#getMembershipNestingDepth()
      */
     @Property(
             label = "User membership nesting depth",
@@ -152,12 +152,38 @@ public class DefaultSyncConfigImpl exten
     public static final String PARAM_USER_MEMBERSHIP_NESTING_DEPTH = "user.membershipNestingDepth";
 
     /**
-     * @see DefaultSyncConfigImpl.Group#getExpirationTime()
+     * @see DefaultSyncConfig.User#getDynamicMembership()
+     */
+    public static final boolean PARAM_USER_DYNAMIC_MEMBERSHIP_DEFAULT = false;
+
+    /**
+     * Configuration option to enable dynamic group membership. If enabled the
+     * implementation will no longer synchronized group accounts into the repository
+     * but instead will enable a dedicated principal management: This results in
+     * external users having their complete principal set as defined external IDP
+     * synchronized to the repository asserting proper population of the
+     * {@link javax.security.auth.Subject} upon login. Please note that the external
+     * groups are reflected through the built-in principal management and thus can
+     * be retrieved for authorization purposes. However, the information is no
+     * longer reflected through the Jackrabbit user management API.
+     *
+     * @see DefaultSyncConfig.User#getDynamicMembership()
+     */
+    @Property(
+            label = "User Dynamic Membership",
+            description = "If enabled membership of external identities (user) is no longer fully reflected " +
+                    "within the repositories user management.",
+            boolValue = PARAM_USER_DYNAMIC_MEMBERSHIP_DEFAULT
+    )
+    public static final String PARAM_USER_DYNAMIC_MEMBERSHIP = "user.dynamicMembership";
+
+    /**
+     * @see DefaultSyncConfig.Group#getExpirationTime()
      */
     public static final String PARAM_GROUP_EXPIRATION_TIME_DEFAULT = "1d";
 
     /**
-     * @see DefaultSyncConfigImpl.Group#getExpirationTime()
+     * @see DefaultSyncConfig.Group#getExpirationTime()
      */
     @Property(
             label = "Group Expiration Time",
@@ -167,12 +193,12 @@ public class DefaultSyncConfigImpl exten
     public static final String PARAM_GROUP_EXPIRATION_TIME = "group.expirationTime";
 
     /**
-     * @see DefaultSyncConfigImpl.Group#getAutoMembership()
+     * @see DefaultSyncConfig.Group#getAutoMembership()
      */
     public static final String[] PARAM_GROUP_AUTO_MEMBERSHIP_DEFAULT = {};
 
     /**
-     * @see DefaultSyncConfigImpl.Group#getAutoMembership()
+     * @see DefaultSyncConfig.Group#getAutoMembership()
      */
     @Property(
             label = "Group auto membership",
@@ -183,12 +209,12 @@ public class DefaultSyncConfigImpl exten
     public static final String PARAM_GROUP_AUTO_MEMBERSHIP = "group.autoMembership";
 
     /**
-     * @see DefaultSyncConfigImpl.Group#getPropertyMapping()
+     * @see DefaultSyncConfig.Group#getPropertyMapping()
      */
     public static final String[] PARAM_GROUP_PROPERTY_MAPPING_DEFAULT = {};
 
     /**
-     * @see DefaultSyncConfigImpl.Group#getPropertyMapping()
+     * @see DefaultSyncConfig.Group#getPropertyMapping()
      */
     @Property(
             label = "Group property mapping",
@@ -199,12 +225,12 @@ public class DefaultSyncConfigImpl exten
     public static final String PARAM_GROUP_PROPERTY_MAPPING = "group.propertyMapping";
 
     /**
-     * @see DefaultSyncConfigImpl.Group#getPathPrefix()
+     * @see DefaultSyncConfig.Group#getPathPrefix()
      */
     public static final String PARAM_GROUP_PATH_PREFIX_DEFAULT = "";
 
     /**
-     * @see DefaultSyncConfigImpl.Group#getPathPrefix()
+     * @see DefaultSyncConfig.Group#getPathPrefix()
      */
     @Property(
             label = "Group Path Prefix",
@@ -229,6 +255,7 @@ public class DefaultSyncConfigImpl exten
         cfg.user()
                 .setMembershipExpirationTime(getMilliSeconds(params, PARAM_USER_MEMBERSHIP_EXPIRATION_TIME, PARAM_USER_MEMBERSHIP_EXPIRATION_TIME_DEFAULT, ONE_HOUR))
                 .setMembershipNestingDepth(params.getConfigValue(PARAM_USER_MEMBERSHIP_NESTING_DEPTH, PARAM_USER_MEMBERSHIP_NESTING_DEPTH_DEFAULT))
+                .setDynamicMembership(params.getConfigValue(PARAM_USER_DYNAMIC_MEMBERSHIP, PARAM_USER_DYNAMIC_MEMBERSHIP_DEFAULT))
                 .setExpirationTime(getMilliSeconds(params, PARAM_USER_EXPIRATION_TIME, PARAM_USER_EXPIRATION_TIME_DEFAULT, ONE_HOUR))
                 .setPathPrefix(params.getConfigValue(PARAM_USER_PATH_PREFIX, PARAM_USER_PATH_PREFIX_DEFAULT))
                 .setAutoMembership(params.getConfigValue(PARAM_USER_AUTO_MEMBERSHIP, PARAM_USER_AUTO_MEMBERSHIP_DEFAULT))

Modified: jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandler.java?rev=1756777&r1=1756776&r2=1756777&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandler.java (original)
+++ jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandler.java Thu Aug 18 13:15:22 2016
@@ -103,7 +103,11 @@ public class DefaultSyncHandler implemen
     @Override
     public SyncContext createContext(@Nonnull ExternalIdentityProvider idp, @Nonnull UserManager userManager,
                                      @Nonnull ValueFactory valueFactory) throws SyncException {
-        return new DefaultSyncContext(config, idp, userManager, valueFactory);
+        if (config.user().getDynamicMembership()) {
+            return new DynamicSyncContext(config, idp, userManager, valueFactory);
+        } else {
+            return new DefaultSyncContext(config, idp, userManager, valueFactory);
+        }
     }
 
     /**

Modified: jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java?rev=1756777&r1=1756776&r2=1756777&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java (original)
+++ jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java Thu Aug 18 13:15:22 2016
@@ -17,14 +17,13 @@
 package org.apache.jackrabbit.oak.spi.security.authentication.external.impl;
 
 import java.security.Principal;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 
+import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 import javax.jcr.Credentials;
-import javax.jcr.SimpleCredentials;
 import javax.security.auth.Subject;
 import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.login.LoginException;
@@ -40,11 +39,13 @@ import org.apache.jackrabbit.oak.spi.sec
 import org.apache.jackrabbit.oak.spi.security.authentication.AuthInfoImpl;
 import org.apache.jackrabbit.oak.spi.security.authentication.ImpersonationCredentials;
 import org.apache.jackrabbit.oak.spi.security.authentication.PreAuthenticatedLogin;
+import org.apache.jackrabbit.oak.spi.security.authentication.credentials.SimpleCredentialsSupport;
 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.ExternalIdentityProviderManager;
 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.credentials.CredentialsSupport;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncContext;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncException;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncHandler;
@@ -56,13 +57,13 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * ExternalLoginModule implements a LoginModule that uses and external identity provider for login.
+ * {@code ExternalLoginModule} implements a {@code LoginModule} that uses an
+ * {@link ExternalIdentityProvider} for authentication.
  */
 public class ExternalLoginModule extends AbstractLoginModule {
 
     private static final Logger log = LoggerFactory.getLogger(ExternalLoginModule.class);
 
-    // todo: make configurable
     private static final int MAX_SYNC_ATTEMPTS = 50;
 
     /**
@@ -79,6 +80,8 @@ public class ExternalLoginModule extends
 
     private SyncManager syncManager;
 
+    private CredentialsSupport credentialsSupport = SimpleCredentialsSupport.getInstance();
+
     /**
      * internal configuration when invoked from a factory rather than jaas
      */
@@ -121,8 +124,8 @@ public class ExternalLoginModule extends
 
     //--------------------------------------------------------< LoginModule >---
     @Override
-    public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> ss, Map<String, ?> opts) {
-        super.initialize(subject, callbackHandler, ss, opts);
+    public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> opts) {
+        super.initialize(subject, callbackHandler, sharedState, opts);
 
         // merge options with osgi options if needed
         if (osgiConfig != null) {
@@ -168,6 +171,12 @@ public class ExternalLoginModule extends
                 }
             }
         }
+
+        if (idp instanceof CredentialsSupport) {
+            credentialsSupport = (CredentialsSupport) idp;
+        } else {
+            log.debug("No 'SupportedCredentials' configured. Using default implementation supporting 'SimpleCredentials'.");
+        }
     }
 
     @Override
@@ -178,18 +187,16 @@ public class ExternalLoginModule extends
         credentials = getCredentials();
 
         // check if we have a pre authenticated login from a previous login module
-        final String userId;
         final PreAuthenticatedLogin preAuthLogin = getSharedPreAuthLogin();
-        if (preAuthLogin != null) {
-            userId = preAuthLogin.getUserId();
-        } else {
-            userId = credentials instanceof SimpleCredentials ? ((SimpleCredentials) credentials).getUserID() : null;
-        }
+        final String userId = getUserId(preAuthLogin, credentials);
+
         if (userId == null && credentials == null) {
-            log.debug("No credentials found for external login module. ignoring.");
+            log.debug("No credentials|userId found for external login module. ignoring.");
             return false;
         }
 
+        // remember identification for log-output
+        Object logId = (userId != null) ? userId : credentials;
         try {
             SyncedIdentity sId = null;
             UserManager userMgr = getUserManager();
@@ -237,11 +244,7 @@ public class ExternalLoginModule extends
                 return true;
             } else {
                 if (log.isDebugEnabled()) {
-                    if (userId != null) {
-                        log.debug("IDP {} returned null for simple creds of {}", idp.getName(), userId);
-                    } else {
-                        log.debug("IDP {} returned null for {}", idp.getName(), credentials);
-                    }
+                    log.debug("IDP {} returned null for {}", idp.getName(), logId);
                 }
 
                 if (sId != null) {
@@ -252,16 +255,13 @@ public class ExternalLoginModule extends
                 return false;
             }
         } catch (ExternalIdentityException e) {
-            log.error("Error while authenticating '{}' with {}",
-                    userId == null ? credentials : userId, idp.getName(), e);
+            log.error("Error while authenticating '{}' with {}", logId, idp.getName(), e);
             return false;
         } catch (LoginException e) {
-            log.debug("IDP {} throws login exception for '{}': {}",
-                    idp.getName(), userId == null ? credentials : userId, e.getMessage());
+            log.debug("IDP {} throws login exception for '{}': {}", idp.getName(), logId, e.getMessage());
             throw e;
         } catch (Exception e) {
-            log.debug("SyncHandler {} throws sync exception for '{}'",
-                    syncHandler.getName(), userId == null ? credentials : userId, e);
+            log.debug("SyncHandler {} throws sync exception for '{}'", syncHandler.getName(), logId, e);
             LoginException le = new LoginException("Error while syncing user.");
             le.initCause(e);
             throw le;
@@ -299,6 +299,19 @@ public class ExternalLoginModule extends
         return true;
     }
 
+    //------------------------------------------------------------< private >---
+
+    @CheckForNull
+    private String getUserId(@CheckForNull PreAuthenticatedLogin preAuthLogin, @CheckForNull Credentials credentials) {
+        if (preAuthLogin != null) {
+            return preAuthLogin.getUserId();
+        } else if (credentials != null){
+            return credentialsSupport.getUserId(credentials);
+        } else {
+            return null;
+        }
+    }
+
     /**
      * Initiates synchronization of the external user.
      * @param user the external user
@@ -385,14 +398,11 @@ public class ExternalLoginModule extends
         Map<String, Object> attributes = new HashMap<String, Object>();
         Object shared = sharedState.get(SHARED_KEY_ATTRIBUTES);
         if (shared instanceof Map) {
-            for (Object key : ((Map) shared).keySet()) {
-                attributes.put(key.toString(), ((Map) shared).get(key));
-            }
-        } else if (creds instanceof SimpleCredentials) {
-            SimpleCredentials sc = (SimpleCredentials) creds;
-            for (String attrName : sc.getAttributeNames()) {
-                attributes.put(attrName, sc.getAttribute(attrName));
+            for (Map.Entry entry : ((Map<?,?>) shared).entrySet()) {
+                attributes.put(entry.getKey().toString(), entry.getValue());
             }
+        } else if (creds != null) {
+            attributes.putAll(credentialsSupport.getAttributes(creds));
         }
         return new AuthInfoImpl(userId, attributes, principals);
     }
@@ -407,22 +417,22 @@ public class ExternalLoginModule extends
     }
 
     /**
-     * @return An immutable set containing only the {@link SimpleCredentials} class.
+     * @return the set of credentials classes as exposed by the configured
+     * {@link CredentialsSupport} implementation.
      */
     @Nonnull
     @Override
     protected Set<Class> getSupportedCredentials() {
-        // TODO: maybe delegate getSupportedCredentials to IDP
-        Class scClass = SimpleCredentials.class;
-        return Collections.singleton(scClass);
+        return credentialsSupport.getCredentialClasses();
     }
 
+    //----------------------------------------------< public setters (JAAS) >---
 
-    public void setSyncManager(SyncManager syncManager) {
+    public void setSyncManager(@Nonnull SyncManager syncManager) {
         this.syncManager = syncManager;
     }
 
-    public void setIdpManager(ExternalIdentityProviderManager idpManager) {
+    public void setIdpManager(@Nonnull ExternalIdentityProviderManager idpManager) {
         this.idpManager = idpManager;
     }
 }
\ No newline at end of file

Modified: jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalProvider.java?rev=1756777&r1=1744292&r2=1756777&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalProvider.java (original)
+++ jackrabbit/oak/branches/1.2/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalProvider.java Thu Aug 18 13:15:22 2016
@@ -207,7 +207,7 @@ class ExternalGroupPrincipalProvider imp
             String statement = "SELECT '" + REP_EXTERNAL_PRINCIPAL_NAMES + "' FROM [rep:User] WHERE PROPERTY(["
                     + REP_EXTERNAL_PRINCIPAL_NAMES + "], '" + PropertyType.TYPENAME_STRING + "')"
                     + op + "$" + BINDING_PRINCIPAL_NAMES + QueryEngine.INTERNAL_SQL2_QUERY;
-            return root.getQueryEngine().executeQuery(statement, Query.JCR_SQL2, bindings, namePathMapper.getSessionLocalMappings());
+            return root.getQueryEngine().executeQuery(statement, Query.JCR_SQL2, Long.MAX_VALUE, 0, bindings, namePathMapper.getSessionLocalMappings());
         } catch (ParseException e) {
             return null;
         }

Copied: jackrabbit/oak/branches/1.2/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/AbstractExternalAuthTest.java (from r1740114, jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/AbstractExternalAuthTest.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/AbstractExternalAuthTest.java?p2=jackrabbit/oak/branches/1.2/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/AbstractExternalAuthTest.java&p1=jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/AbstractExternalAuthTest.java&r1=1740114&r2=1756777&rev=1756777&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/AbstractExternalAuthTest.java (original)
+++ jackrabbit/oak/branches/1.2/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/AbstractExternalAuthTest.java Thu Aug 18 13:15:22 2016
@@ -16,13 +16,17 @@
  */
 package org.apache.jackrabbit.oak.spi.security.authentication.external;
 
+import java.security.PrivilegedExceptionAction;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
+import javax.jcr.NoSuchWorkspaceException;
 import javax.jcr.RepositoryException;
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginException;
 
 import com.google.common.base.Function;
 import com.google.common.base.Predicates;
@@ -31,7 +35,12 @@ import com.google.common.collect.Sets;
 import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.jackrabbit.api.security.user.UserManager;
 import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.api.ContentSession;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
+import org.apache.jackrabbit.oak.spi.security.authentication.SystemSubject;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.basic.DefaultSyncConfig;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.principal.ExternalPrincipalConfiguration;
 import org.junit.After;
 import org.junit.Before;
 
@@ -50,6 +59,9 @@ public abstract class AbstractExternalAu
 
     private Set<String> ids;
 
+    private ContentSession systemSession;
+    private Root systemRoot;
+
     @Before
     public void before() throws Exception {
         super.before();
@@ -67,6 +79,10 @@ public abstract class AbstractExternalAu
             destroyIDP();
             idp = null;
 
+            if (systemSession != null) {
+                systemSession.close();
+            }
+
             // discard any pending changes
             root.refresh();
 
@@ -106,6 +122,13 @@ public abstract class AbstractExternalAu
         }), Predicates.notNull());
     }
 
+    @Override
+    protected SecurityProvider getSecurityProvider() {
+        if (securityProvider == null) {
+            securityProvider = new TestSecurityProvider(getSecurityConfigParameters(), new ExternalPrincipalConfiguration());
+        }
+        return securityProvider;
+    }
 
     protected ExternalIdentityProvider createIDP() {
         return new TestIdentityProvider();
@@ -127,4 +150,17 @@ public abstract class AbstractExternalAu
         syncConfig.user().setMembershipNestingDepth(1);
         return syncConfig;
     }
+
+    protected Root getSystemRoot() throws Exception {
+        if (systemRoot == null) {
+            systemSession = Subject.doAs(SystemSubject.INSTANCE, new PrivilegedExceptionAction<ContentSession>() {
+                @Override
+                public ContentSession run() throws LoginException, NoSuchWorkspaceException {
+                    return getContentRepository().login(null, null);
+                }
+            });
+            systemRoot = systemSession.getLatestRoot();
+        }
+        return systemRoot;
+    }
 }
\ No newline at end of file