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 an...@apache.org on 2023/02/16 16:47:43 UTC

[jackrabbit-oak] branch OAK-10069 created (now 84ff0c267d)

This is an automated email from the ASF dual-hosted git repository.

angela pushed a change to branch OAK-10069
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git


      at 84ff0c267d OAK-10069 : Best practices on how to setup access control external identities

This branch includes the following new commits:

     new 84ff0c267d OAK-10069 : Best practices on how to setup access control external identities

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[jackrabbit-oak] 01/01: OAK-10069 : Best practices on how to setup access control external identities

Posted by an...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

angela pushed a commit to branch OAK-10069
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git

commit 84ff0c267d4a35a28f27fbb74897754e4206311b
Author: angela <an...@adobe.com>
AuthorDate: Thu Feb 16 17:47:26 2023 +0100

    OAK-10069 : Best practices on how to setup access control external identities
---
 oak-doc/src/site/markdown/dos_and_donts.md         |   1 +
 .../authentication/external/bestpractices.md       | 159 +++++++++++++++++++++
 .../authentication/external/defaultusersync.md     |  47 +++---
 .../security/authentication/external/dynamic.md    |  32 +++--
 .../external/externallogin_examples.md             |  88 +++++++++++-
 .../security/authentication/externalloginmodule.md |   3 +-
 .../security/authorization/bestpractices.md        |   1 +
 oak-doc/src/site/markdown/security/overview.md     |   2 +
 oak-doc/src/site/markdown/security/principal.md    |   6 +-
 9 files changed, 301 insertions(+), 38 deletions(-)

diff --git a/oak-doc/src/site/markdown/dos_and_donts.md b/oak-doc/src/site/markdown/dos_and_donts.md
index 41b32dc227..fda15e06a4 100644
--- a/oak-doc/src/site/markdown/dos_and_donts.md
+++ b/oak-doc/src/site/markdown/dos_and_donts.md
@@ -122,6 +122,7 @@ c = d.getParent();                              // preferred way to fetch the pa
 ```
 ## Security
 - [Best Practices for Authorization](security/authorization/bestpractices.html)
+- [Best Practices for External Authentication](security/authentication/external/bestpractices.html)
 
 ## Misc
 ### Don't use Thread.interrupt()
diff --git a/oak-doc/src/site/markdown/security/authentication/external/bestpractices.md b/oak-doc/src/site/markdown/security/authentication/external/bestpractices.md
new file mode 100644
index 0000000000..b2ef8bfbf4
--- /dev/null
+++ b/oak-doc/src/site/markdown/security/authentication/external/bestpractices.md
@@ -0,0 +1,159 @@
+<!--
+   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.
+-->
+
+# Best Practices for External Authentication
+
+<!-- MACRO{toc} -->
+
+## Before you get started
+
+Before you get started make sure you are familiar with the basic concepts of JCR authentication, and it's implementation 
+in Apache Jackrabbit Oak.
+
+External authentication in Oak refers to integrating a third party identity provider like LDAP or SAML into the 
+authentication setup optionally combining it with other built-in authentication mechanisms.
+
+## Best Practices 
+
+### JAAS Setup
+
+When combining external authentication with other built-in or custom 
+[login modules](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/javax/security/auth/spi/LoginModule.html) 
+make sure to define a 
+[configuration](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/javax/security/auth/login/Configuration.html) 
+with the optimal order and the proper [control flag](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/javax/security/auth/login/AppConfigurationEntry.LoginModuleControlFlag.html) 
+for each module to cover all cases.
+
+Additional reading: https://docs.oracle.com/en/java/javase/11/security/appendix-b-jaas-login-configuration-file.html#GUID-7EB80FA5-3C16-4016-AED6-0FC619F86F8E
+
+#### Combination with Token Authentication
+
+Whenever JCR sessions created with Oak are short-lived (e.g. only lasting for a single HTTP request) authentication 
+against an external IDP may not perform well. It is therefore recommended to use external authentication in combination 
+with an additional authentication mechanism like e.g. the built-in [token login](../tokenmanagement.html).
+
+Make sure the token-login is 'sufficient' and is evaluated prior to the external login that connects to the external IDP.
+
+#### Combination with Default Authentication
+
+Oak comes with a default login for user accounts stored and managed inside the JCR content repository. This also includes 
+support for default users like an anonymous guest, and an administrator with full access to the repository. If this is 
+desired, it is recommend to also add the [default `LoginModule`](../default.html#uid_pw) to the JAAS configuration.
+
+The optional order depends on the frequency of default vs external login.
+
+##### Example JAAS Configuration
+
+The following JAAS configuration can e.g. be used when running an Oak repository with external authentication 
+in combination with Apache Sling (see also other [examples](externallogin_examples.html)):
+
+| Ranking | Control Flag | LoginModule Class Name |
+|---------|--------------|------------------------|
+| 300     | OPTIONAL     | org.apache.jackrabbit.oak.spi.security.authentication.GuestLoginModule |
+| 200     | SUFFICIENT   | org.apache.jackrabbit.oak.security.authentication.token.TokenLoginModule | 
+| 150     | SUFFICIENT   | org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModuleFactory |
+| 100     | SUFFICIENT   | org.apache.jackrabbit.oak.security.authentication.user.LoginModuleImpl |
+
+### Synchronization of Users and Groups
+
+The external authentication module in Oak comes with the option to synchronize external identities into the content 
+repository (see section [User and Group Synchronization](../usersync.html)).
+
+The following best practices should be followed:
+
+#### External Identity Provider as SSOT
+
+Your external identity provider should be considered the single source of truth (SSOT) for all users and groups defined 
+and managed by it. 
+
+In contrast, the data synchronized into the repository should be considered a volatile cache and ideally 
+are immutable (i.e. only maintained by system sessions in charge of the synchronization). 
+
+The following features provided by the _oak-auth-external_ module help to prevent unintended modification of synchronized 
+external identities:
+
+- [Dynamic Membership](defaultusersync.html#dynamic_membership): Enabling dynamic membership will result in membership information being stored in 
+a protected property that cannot be altered using regular JCR write or Jackrabbit user management API. 
+- [Dynamic Group](defaultusersync.html#dynamic_groups): Can be used in combination with dynamic membership when the application requires group principals 
+to also exposed through `UserManager` (and not just through `PrincipalManager` as it would be needed for permission setup).
+Note though that these group accounts cannot have members added (see section [Enforcing dynamic groups](defaultusersync.html#enforcing_dynamic_groups))
+- [Protecting External Identities](defaultusersync.html#protect_external_identities): The module comes with [configuration 
+ option](defaultusersync.html#configuration_principals) to protect external identities. If enabled (as warning or as full 
+ protection) a dedicated validator that will report/fail attempts to modify synchronized external identities. This will 
+ help to identify violations of the immutability contract.
+ 
+#### User Management for External Identities
+
+- Properties and membership for external identities must be managed in the external IDP. Changes made in the JCR repository 
+using user management API will be overwritten upon the next sync.
+- Never set a password for external users to make sure uid/pw login gets authenticated against the external IDP and never 
+against the synchronized user in the repository.
+
+#### Membership Nesting
+
+For performance reasons avoid defining unnecessary membership nesting that increase the number of indirections (see 
+[Best Practices for Authorization](../../authorization/bestpractices.html)).
+
+#### Membership crossing IDP boundaries
+
+Introducing membership crossing IDP boundaries should be considered a trust boundary violation.
+
+If adding external identities to local groups cannot be avoided please make sure to leverage 
+[conditional auto-membership](defaultusersync.html#configuration_automembership) 
+or auto-membership configuration in combination with dynamic membership (see 
+[Configuration of the DefaultSyncHandler](defaultusersync.html#configuration_sync_handler)).
+
+### Authorization for External Identities
+
+Upon repository login through external authentication the subject is populated with principals obtained from the 
+external identity provider. 
+
+In addition, the configured auto-membership will be resolved for the external user and its external groups (see 
+autoMembership configuration [options](defaultusersync.html#configuration_sync_handler) and section [Automatic Membership with AutoMembershipConfig](defaultusersync.html#configuration_automembership))
+
+The authenticated session will be subject to regular Oak permission evaluation as defined for the instance and 
+described in section [Permissions](../../permission.html). 
+
+#### Access control setup
+
+Synchronized external identities (both in default and in dynamic sync mode) are exposed as principals through the 
+[Principal Management API](../../principal.html) and can be used for access control setup as described 
+in [Access Control Management](../../accesscontrol.html).
+
+See also section [Best Practices for Authorization](../../authorization/bestpractices.html)) for recommendations.
+
+The following options exist if access control setup for external groups should be ready before the first user login:
+
+- Pre-sync external groups to make them available to the principal manager (see next section)
+- Configure [ImportMode](../../accesscontrol/default.html#configuration)=`besteffort` with the default Oak 
+  authorization setup and define access control content for principals before they exist.
+  
+#### Pre-sync of external groups
+
+The following 2 options exist to populate the repository with external group principals before the first user login in 
+order to setup access control:
+
+- The _oak-auth-external_ module comes with a JMX integration that allows for synchronization of external identities outside 
+of the regular repository login. See [JMX Synchronization Tool](../usersync.html#jmx-synchronization-tool) and
+[SynchronizationMBean](https://jackrabbit.apache.org/oak/docs/apidocs/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/jmx/SynchronizationMBean.html) 
+for details. This requires the `ExternalIdentityProvider` to implement the methods required to retrieve external 
+identities outside of the authentication step. In general this is the recommended way to pre-sync groups.
+- In case the `ExternalIdentityProvider` does not support user and group sync outside of the regular 
+repository login, external identities can be created using Jackrabbit User Management API. It is important to note though
+that the `rep:externalId` cannot be added or changed once the group has been persisted as the property is system maintained 
+and protected. Note that mistakes in defining the `rep:externalId`, `rep:authorizableId` or `rep:principalName` properties 
+will result in mismatches during authentication, sync and permission evaluation that cannot be corrected.
diff --git a/oak-doc/src/site/markdown/security/authentication/external/defaultusersync.md b/oak-doc/src/site/markdown/security/authentication/external/defaultusersync.md
index 8b13c8d5eb..55141ad3a4 100644
--- a/oak-doc/src/site/markdown/security/authentication/external/defaultusersync.md
+++ b/oak-doc/src/site/markdown/security/authentication/external/defaultusersync.md
@@ -15,12 +15,14 @@
    limitations under the License.
 -->
 
-User and Group Synchronization : The Default Implementation
+# User and Group Synchronization : The Default Implementation
 --------------------------------------------------------------------------------
 
-### Default Implementation of Sync API
+<!-- MACRO{toc} -->
 
-#### SyncManager
+## Default Implementation of Sync API
+
+### SyncManager
 
 The default implementation (`SyncManagerImpl`) is intended for use in an OSGi-base
 repository setup: it tracks all `SyncHandler` registered via OSGi.
@@ -28,20 +30,20 @@ repository setup: it tracks all `SyncHandler` registered via OSGi.
 It can be used in non-OSGi environments by passing a `org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard`
 to the constructor.
 
-#### SyncHandler
+### SyncHandler
 
 The [DefaultSyncHandler] comes with a set of configuration options that
 allow to specify the synchronization behavior (see below). Depending on the 
 configuration it chooses between two different `SyncContext` implementations.
 
-#### SyncContext
+### SyncContext
 
 Oak provides the following implementations of the [SyncContext] interface:
 
 - [DefaultSyncContext]: base implementation that synchronizes external user and group accounts into the repository
 - [DynamicSyncContext]: derived implementation that provides special handling for external groups.
  
-##### DefaultSyncContext
+#### DefaultSyncContext
 
 All users/groups synchronized by this context will get the following properties set.
 These properties allow to run separate task for periodical update and make sure
@@ -59,7 +61,7 @@ for further details.
 The [DefaultSyncContext] is exported as part of the 'basic' package space and
 may be used to provide custom implementations.
 
-##### DynamicSyncContext
+#### DynamicSyncContext
 
 Extending from the [DefaultSyncContext] this implementation that provides special 
 handling  for external groups in case the [Dynamic Group Membership](#dynamic_membership) 
@@ -70,21 +72,22 @@ the group principal names of the external user accounts:
 
 - `rep:externalPrincipalNames` : Optional system-maintained property related to [Dynamic Group Membership](#dynamic_membership)
 
-#### SyncResult
+### SyncResult
 
 The [DefaultSyncResultImpl] is exported as part of the 'basic' package space 
 providing a simple `SyncResult` implementation based on a status and a [DefaultSyncedIdentity].
 
 
-#### SyncedIdentity
+### SyncedIdentity
 
 The [DefaultSyncedIdentity] is exported as part of the 'basic' package space. It 
 maps the ID of a synchronized user/group account to the external identity references
 represented by [ExternalIdentityRef].
 
 
+### Dynamic Sync
 <a name="dynamic_membership"></a>
-### Dynamic Group Membership
+#### Dynamic Group Membership
 
 As of Oak 1.5.3 the default sync handler comes with an addition configuration 
 option that allows enabling dynamic group membership resolution for external users. 
@@ -95,7 +98,7 @@ The details and effects on other security related modules are described in
 section [Dynamic Membership and Dynamic Groups](dynamic.html). 
 
 <a name="dynamic_groups"></a>
-### Dynamic Groups
+#### Dynamic Groups
 
 As of Oak 1.46.0 there exists the option to leverage [Dynamic Membership](#dynamic_membership) in combination with a 
 new `Dynamic Groups` configuration option (see also [OAK-9803]). If both options are enabled external groups will continue 
@@ -104,7 +107,7 @@ User Management API without losing the benefits of the dynamic membership.
 See section [Dynamic Membership and Dynamic Groups](dynamic.html) for details and comparison.
 
 <a name="xml_import"></a>
-#### XML Import
+### XML Import
 
 The protected nature of the `rep:externalPrincipalNames` is also reflected during
 XML import of user accounts:
@@ -118,9 +121,9 @@ the target system the sync will then result in a full sync of group membership o
 will re-create the `rep:externalPrincipalNames` property.
 
 <a name="validation"></a>
-#### Validation
+### Validation
 
-##### rep:externalPrincipalNames
+#### rep:externalPrincipalNames
 
 As of Oak 1.5.3 a dedicated `Validator` implementation asserts that the protected,
 system-maintained property `rep:externalPrincipalNames` is only written by the 
@@ -140,7 +143,7 @@ with external user/group accounts.
 | 0072              | Property 'rep:externalPrincipalNames' requires 'rep:externalId' to be present on the Node. |
 | 0073              | Property 'rep:externalId' cannot be removed if 'rep:externalPrincipalNames' is present. |
 
-##### rep:externalId
+#### rep:externalId
 
 If protection of the `rep:externalId` property is enabled (since Oak 1.5.8) the
 validator performs the following checks:
@@ -150,7 +153,8 @@ validator performs the following checks:
 | 0074              | Attempt to add, modify or remove the system maintained property 'rep:externalId'. |
 | 0075              | Property 'rep:externalId' may only have a single value of type STRING. |
  
-##### Protecting synchronized external users/groups 
+<a name="protect_external_identities"></a> 
+#### Protecting synchronized external users/groups 
 
 If protection of synchronized external users/groups is enabled (since Oak 1.44.0) an additional validator is present
 which either warns upon or prevents creation, modification and removal of external identities that have been synchronized 
@@ -175,7 +179,8 @@ The following constraint violations will be reported:
 | 0076 | Attempt to remove protected external identity '%s'                         |
 | 0076 | Attempt to remove node '%s' from protected external identity               |
 
-##### Enforcing dynamic groups
+<a name="enforcing_dynamic_groups"></a> 
+#### Enforcing dynamic groups
 
 If `user.dynamicMembership` is enabled together with `group.dynamicGroups` a separate validator will be present to
 make sure no members are added to the dynamic groups through regular API calls (`Group.addMember(Authorizable)` and 
@@ -196,6 +201,7 @@ to a dynamic external group:
 <a name="configuration"></a>
 ### Configuration
 
+<a name="configuration_sync_handler"></a>
 #### Configuration of the DefaultSyncHandler
 
 The default `SyncHandler` implementations are configured via [DefaultSyncConfig]:
@@ -219,6 +225,12 @@ The default `SyncHandler` implementations are configured via [DefaultSyncConfig]
 | Group 'Dynamic Groups'        | `group.dynamicGroups`         | Only takes effect in combination with `user.dynamicMembership` and will result in external groups being synced as dynamic groups. |
 | | | |
 
+Note, that the following options relate to the [dynamic sync](dynamic.html) feature:
+- `user.dynamicMembership` : Enabling dynamic membership for external users.
+- `user.enforceDynamicMembership` : If enabled together with `user.dynamicMembership` previously synced membership information will be migrated to dynamic membership upon user sync. Otherwise it takes no effect.
+- `group.dynamicGroups` : Only takes effect in combination with `user.dynamicMembership` and will result in external groups being synced as dynamic groups.
+
+<a name="configuration_automembership"></a>
 #### Automatic Membership with AutoMembershipConfig
 Since Oak 1.42.0 ([OAK-9463]) the auto-membership behavior can be extended to allow for conditional group membership 
 based on characteristics of a given synced external identity. In addition to configuration options `group.autoMembership` 
@@ -230,6 +242,7 @@ The `DefaultSyncHandler` is tracking services implementing [AutoMembershipConfig
 If present the additional membership defined by the [AutoMembershipConfig], will be reflected upon default and dynamic 
 sync together with the original, 'global' auto-membership configuration.
 
+<a name="configuration_principals"></a>
 #### Configuration of the 'Apache Jackrabbit Oak External PrincipalConfiguration'
 
 Please note that the `ExternalPrincipalConfiguration` _("Apache Jackrabbit Oak External PrincipalConfiguration")_ 
diff --git a/oak-doc/src/site/markdown/security/authentication/external/dynamic.md b/oak-doc/src/site/markdown/security/authentication/external/dynamic.md
index 1be242c2c7..f0ed493c7f 100644
--- a/oak-doc/src/site/markdown/security/authentication/external/dynamic.md
+++ b/oak-doc/src/site/markdown/security/authentication/external/dynamic.md
@@ -15,14 +15,16 @@
    limitations under the License.
 -->
 
-User and Group Synchronization : Dynamic Membership and Dynamic Groups
+# User and Group Synchronization : Dynamic Membership and Dynamic Groups
 ----------------------------------------------------------------------
 
+<!-- MACRO{toc} -->
+
 As of Oak 1.5.3 the default sync handler comes with an additional configuration 
 option (see section [Configuration](defaultusersync.html#configuration) 
 that allows enabling dynamic group membership resolution for external users. 
 
-Enabling dynamic membership in the [DefaultSyncConfig] will change the way external
+Enabling dynamic sync options in the [DefaultSyncConfig] will change the way external
 groups are synchronized (see [OAK-4101]) and how automatic group membership 
 is being handled (see [OAK-4087]).
 
@@ -32,14 +34,14 @@ The key benefits of dynamic membership resolution are:
 - avoid storing/updating auto-membership which is assigned to all external users
 - ease principal resolution upon repository login
 
-See also [FAQ](faq.html#Dynamic_Sync) for frequently asked questions about thes dynamic sync.
+See also [FAQ](faq.html#Dynamic_Sync) for frequently asked questions about the dynamic sync.
 
-### SyncContext with Dynamic Membership
+## SyncContext with Dynamic Membership
 
 With the default `SyncHandler` this configuration option will show the following 
 effects:
 
-#### External Groups
+### External Groups
 
 - If enabled the handler will use an alternative [SyncContext] to synchronize external groups (`DynamicSyncContext`).
 - Instead of synchronizing membership information alongside the group accounts, this `DynamicSyncContext`
@@ -61,7 +63,7 @@ in Oak 1.6.1 to allow for optimized resolution of a principal names from a given
 of `ExternalIdentityProvider` needs to also implement `PrincipalNameResolver`.
 See also [OAK-5210].
 
-#### Automatic Membership
+### Automatic Membership
 
 - If enabled automatic membership assignment for existing, local groups will not longer be written to the repository
 - Instead, the `ExternalPrincipalConfiguration` _("Apache Jackrabbit Oak External PrincipalConfiguration")_ will keep 
@@ -85,9 +87,9 @@ See also [OAK-5210].
   and reflect autoMembership for synchronized external users in the User Management API (see below).
   The same applies for the conditional auto-membership as introduced with [OAK-9463].
   
-### Effect of Dynamic Membership on other Security Modules
+## Effect of Dynamic Membership on other Security Modules
   
-#### Principal Management
+### Principal Management
 
 The dynamic (principal) membership features comes with a dedicated `PrincipalConfiguration` 
 implementation (i.e. [ExternalPrincipalConfiguration]) that is in charge of securing  
@@ -107,7 +109,7 @@ A given external principal will be accessible though the principal management AP
 if it can be read from any of the `rep:externalPrincipalNames` properties 
 present using a dedicated query.
 
-##### API Overview
+#### API Overview
 
 - `extUserName`       : the principal name of an external user
 - `extGroupName`      : the principal name of an external group
@@ -121,8 +123,8 @@ present using a dedicated query.
 | `PrincipalManager.getGroupMembership(extUserPrincipal)`  | ok           | ok                 | ok                     | Dynamic group principals include both declared external groups and configured auto-membership principals (including inherited principals).|
 | `PrincipalManager.getGroupMembership(extGroupPrincipal)` | ok           | - <sup>2</sup>     | - <sup>2,3</sup>       | <sup>2</sup> Group membership gets flattened and stored with the external user. Group-group relationship is not preserved.<br/><sup>3</sup> For dynamic groups synced into the repository the configured auto-membership principals are resolved, see also user management API below.  |
 
-#### User Management
-##### User Management without Dynamic Groups Option
+### User Management
+#### User Management without Dynamic Groups Option
 
 Unless the 'Dynamic Groups' option is set additionally, the dynamic membership option will effectively disable the
 synchronization of the external group account information into the repository's user management feature.
@@ -148,7 +150,7 @@ of external user identities reflected in the corresponding API calls, most notab
 `Group.isDeclaredMember`, `Group.getMembers`, `Group.getDeclaredMembers` as well as `Authorizable.memberOf`
 and `Authorizable.declaredMemberOf()`.
 
-##### User Management with Dynamic Groups Option enabled
+#### User Management with Dynamic Groups Option enabled
 
 If the 'Dynamic Groups' flag is turned on in addition, external group accounts will continue to be synchronized into the 
 repository's user management. However, membership information will not be stored together with the groups but instead will 
@@ -164,7 +166,7 @@ Note, that manually adding members to these dynamic external groups using `Group
 equivalent Oak API operations will be prevented by a dedicated validator that is enabled as soon as the _Dynamic Groups_
 option is present together with _Dynamic Membership_.
 
-##### API Overview
+#### API Overview
 
 - `extUserId`  : the ID of a synchronized external user
 - `extGroupId` : the ID of a synchronized external group
@@ -197,7 +199,7 @@ option is present together with _Dynamic Membership_.
 | `autoGroup.getDeclaredMembers()`                         | ok           | (ok) <sup>5,12</sup>| ok <sup>12</sup>      |  |
 | `autoGroup.getMembers()`                                 | ok           | (ok) <sup>5,12</sup>| ok <sup>12</sup>      |  |
 
-#### Authentication
+### Authentication
 
 The authentication setup provided by Oak is not affected by the dynamic membership 
 handling as long as the configured `LoginModule` implementations rely on the 
@@ -205,7 +207,7 @@ handling as long as the configured `LoginModule` implementations rely on the
 _("Apache Jackrabbit Oak External PrincipalConfiguration")_ is properly registered 
 with the `SecurityProvider` (see section [Configuration](defaultusersync.html#configuration)).
 
-#### Authorization
+### Authorization
 
 The authorization modules shipped with Oak only depend on `Principal`s (and not on
 user management functionality) and are therefore not affected by the dynamic 
diff --git a/oak-doc/src/site/markdown/security/authentication/external/externallogin_examples.md b/oak-doc/src/site/markdown/security/authentication/external/externallogin_examples.md
index 2717910b1b..3175c640db 100644
--- a/oak-doc/src/site/markdown/security/authentication/external/externallogin_examples.md
+++ b/oak-doc/src/site/markdown/security/authentication/external/externallogin_examples.md
@@ -18,8 +18,92 @@
 Authentication with External Login Module : Examples
 ----------------------------------------------------
 
-- [Integration with Standard Oak Authentication](#standard)
-- [Integration with Pre-Authentication and Login Module Chain](#preauth)
+<!-- MACRO{toc} -->
+
+<a name="standard-sling"></a>
+### Integration with Standard Oak Authentication used for Apache Sling
+
+The following JAAS configuration can be used in combination with Apache Sling.
+
+#### Example JAAS Configuration
+
+      Example {
+         org.apache.jackrabbit.oak.spi.security.authentication.GuestLoginModule optional;
+         org.apache.jackrabbit.oak.security.authentication.token.TokenLoginModule sufficient;
+         org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModule sufficient
+                                  sync.handlerName="your-synchandler_name"
+                                  idp.name="your_idp_name";
+         org.apache.jackrabbit.oak.security.authentication.user.LoginModuleImpl sufficient;
+         
+       };
+
+#### Understanding the Configuration
+
+##### The LoginModule Sequence
+
+- The `GuestLoginModule` is in charge of handling unauthenticated guest login without passing [GuestCredentials].
+  In other words: if no credentials can be obtained during the login phase, an new instance of [GuestCredentials] is 
+  pushed to the shared state and this module succeeds. Due to the _optional_ flag success is not 
+  required and the authentication proceeds down the list of modules.
+  This module helps to cover non-standard guest login with `null` credentials as it is performed by 
+  Apache Sling (compatibility with Jackrabbit 1.0)
+
+- The `TokenLoginModule` is in charge of handling repository authentication 
+  request with `TokenCredentials`: 
+    - _Login Success_: If token-login succeeds the _sufficient_ flag makes sure
+    authentication does not proceed down the `LoginModule` list. This means
+    that it will not hit the `ExternalIdentityProvider` and will not re-sync
+    an external user as long as the login token is valid.
+    - _Login Failure_: If it fails (e.g. other type of `Credentials`) the authentication
+    will proceed down the `LoginModule` list.
+    - _Commit_: If the login failed the login module will test if the
+    `Credentials` passed to the login ask for generation of a new login token.
+    If this login succeeded it will populate the `Subject` with `Principal`s,
+    `Credentials` and `AuthInfo`.
+    
+    NOTE: In this setup the `TokenLoginModule` is expected to only handle
+    subsequent authentication request after having issued a login token.
+    The latter is achieved by providing `Credentials` attributes that force
+    the `TokenLoginModule` to generate a new login token in the _commit_ phase.
+    The application should then use that login toke for subsequent requests.
+  
+    See [Token Authentication and Token Management](../tokenmanagement.html) for
+    details and for a description of the default implementation.
+    
+- The `ExternalLoginModule` is in charge of handling authentication request for
+  users managed by an `ExternalIdentityProvider`.
+    - _Login Success_: If user authentication against the IDP succeeds
+      the module synchronizes the external user into the repository according
+      to the logic defined in the configure `SyncHandler`. If the user
+      has been synced before it might be updated. If and how often a user
+      gets re-synced is an implementation detail of the `SyncHandler`.
+    - _Login Failure_: If the authentication fails (e.g. wrong IDP or invalid
+      `Credentials`), the login will proceed to the `LoginModuleImpl`.
+    - _Commit_: If the login succeeded the login module will populate the 
+      `Subject` with `Principal`s, `Credentials` and `AuthInfo`.
+   
+      NOTE: if no login token is generated upon first login, any subsequent
+      login for _external_ users will end up being handled by this module 
+      (including connection to the IDP) or fail.
+  
+- The `LoginModuleImpl` is in charge of handling authentication request for
+  users managed and created through the repository's user management API;
+  i.e. users that are not defined by an `ExternalIdentityProvider`. This
+  includes built-in system users like the administrator, the guest-user
+  (aka anonymous) or `SystemUsers`. It also handles impersonation logins.
+    - _Login Success_: If regular user authentication (or impersonation) succeeds
+      the _sufficient_ flag makes sure authentication does not proceed 
+      down the `LoginModule` list i.e. omits unnecessarily trying to 
+      authenticate a local user against the external IDP.
+    - _Login Failure_: If the authentication fails (e.g. no local user that
+      could have uid/pw matching the passed `Credentials`), it will
+      continue down the `LoginModule` list. 
+    - _Commit_: If the login succeeded the login module will populate the 
+      `Subject` with `Principal`s, `Credentials` and `AuthInfo`.
+      
+      NOTE: if no login token is generated upon first login, any subsequent
+      login for _local_ users will end up being handled by this module or fail.
+     
 
 <a name="standard"></a>
 ### Integration with Standard Oak Authentication
diff --git a/oak-doc/src/site/markdown/security/authentication/externalloginmodule.md b/oak-doc/src/site/markdown/security/authentication/externalloginmodule.md
index 60a6bd6b2f..11440b25da 100644
--- a/oak-doc/src/site/markdown/security/authentication/externalloginmodule.md
+++ b/oak-doc/src/site/markdown/security/authentication/externalloginmodule.md
@@ -36,8 +36,9 @@ What it does not:
 * provide a transparent oak principal provider.
 * offer services for background synchronization of users and groups
 
-<a name="details"></a>
+See also [Best Practices for External Authentication](external/bestpractices.html).
 
+<a name="details"></a>
 ### Implementation Details
 The external identity and login handling is split into 3 parts:
 
diff --git a/oak-doc/src/site/markdown/security/authorization/bestpractices.md b/oak-doc/src/site/markdown/security/authorization/bestpractices.md
index 6c4ddebee4..5fad4fc81f 100644
--- a/oak-doc/src/site/markdown/security/authorization/bestpractices.md
+++ b/oak-doc/src/site/markdown/security/authorization/bestpractices.md
@@ -158,6 +158,7 @@ Don't specify redundant access control setup just to be on the safe side:
 
 - If access is granted, avoid repeating the same setup down the hierarchy.
 - Avoid setup for principals with administrative access for which permission evaluation is omitted. It might even create a false sense of security.
+- Avoid redundant membership as it will impact performance of permission evaluation
 
 ### Principal by principle
 
diff --git a/oak-doc/src/site/markdown/security/overview.md b/oak-doc/src/site/markdown/security/overview.md
index 8cdabcc87d..e1fd787a8d 100644
--- a/oak-doc/src/site/markdown/security/overview.md
+++ b/oak-doc/src/site/markdown/security/overview.md
@@ -37,6 +37,7 @@ The Oak Security Layer
      * [User and Group Synchronization](authentication/usersync.html)
      * [Identity Management](authentication/identitymanagement.html)
      * [LDAP Integration](authentication/ldap.html)
+     * [Best Practices](authentication/external/bestpractices.html)
 
 ### Authorization
 
@@ -44,6 +45,7 @@ The Oak Security Layer
      * [Access Control Management](accesscontrol.html)
      * [Permission Evaluation](permission.html)
      * [Combining Multiple Authorization Models](authorization/composite.html)
+     * [Best Practices](authorization/bestpractices.html)
   
 #### Access Control Management
 
diff --git a/oak-doc/src/site/markdown/security/principal.md b/oak-doc/src/site/markdown/security/principal.md
index bcde86c14d..cd3da47856 100644
--- a/oak-doc/src/site/markdown/security/principal.md
+++ b/oak-doc/src/site/markdown/security/principal.md
@@ -21,12 +21,12 @@ Principal Management
 <a name="jcr_api"></a>
 ### JCR API
 
-JCR itself doesn't come with a dedicated principal management API. Nevertheless
-the specification mentions `java.security.Principal` as key feature for access 
+JCR itself doesn't come with a dedicated principal management API. Nevertheless,
+the specification mentions `java.security.Principal` as a key feature for access 
 control management but leaves the discovery of principals to the implementation 
 (see [Section 16.5.7](https://s.apache.org/jcr-2.0-spec/16_Access_Control_Management.html#16.5.7%20Principal%20Discovery)).
 
-Therefore an API for principal management has been defined as part of the
+Therefore, an API for principal management has been defined as part of the
 extensions present with Jackrabbit API.
 
 <a name="jackrabbit_api"></a>