Fork me on GitHub

Authentication with External Login Module : Examples

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 Principals, 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 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 Principals, 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 Principals, 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.

Integration with Standard Oak Authentication

Example JAAS Configuration

  Example {
     org.apache.jackrabbit.oak.security.authentication.token.TokenLoginModule sufficient;
     org.apache.jackrabbit.oak.security.authentication.user.LoginModuleImpl sufficient;
     org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModule required
                     sync.handlerName="your-synchandler_name"
                     idp.name="your_idp_name";
   };

Understanding the Configuration

The LoginModule Sequence
  • 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 Principals, 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 for details and for a description of the default implementation.

  • 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 Principals, 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.

  • 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 whole login will fail because the ExternalLoginModule is configured to be required and the last module in the chain.

    • Commit: If the login succeeded the login module will populate the Subject with Principals, 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.

Login with Different Credentials
GuestCredentials
  • TokenLoginModule will ignore
  • LoginModuleImpl by default supports GuestCredentials; success depends on the existence of a valid guest user in the repository. If it succeeds authentication doesn't move down to ExternalLoginModule.
  • ExternalLoginModule by default doesn't support GuestCredentials but may do if a suitable CredentialsSupport is configured.
SimpleCredentials
  • TokenLoginModule will ignore
  • LoginModuleImpl by default supports SimpleCredentials and it will succeed if the credentials are successfully validated against a local repository user. It is not expected to succeed for synced external users,which should not have their password synced. If it succeeds authentication doesn't move down to ExternalLoginModule.
  • ExternalLoginModule by default support SimpleCredentials and will succeed if authenticating an external against the external IDP including sync is successful. If none of the other modules succeeded the ExternalLoginModule is required to succeed.
TokenCredentials
  • TokenLoginModule supports TokenCredentials and will succeed if the credentials are valid. If it succeeds authentication doesn't move down the module list. If it fails overall authentication is expected to fail as the subsequent modules are not expected to support TokenCredentials.
  • LoginModuleImpl does not support TokenCredentials and will fail.
  • ExternalLoginModule is not expected to support TokenCredentials and thus overall authentication is expected to fail if TokenLoginModule failed.
ImpersonationCredentials
  • TokenLoginModule will ignore
  • LoginModuleImpl by default supports ImpersonationCredentials and it will succeed if impersonation for the target user is allowed. If it succeeds authentication doesn't move down to ExternalLoginModule.
  • ExternalLoginModule by default doesn't support ImpersonationCredentials but may do if a suitable CredentialsSupport is configured.
Other Credentials
  • Overall login success only if the ExternalLoginModule supports these credentials
  • TokenLoginModule will ignore
  • LoginModuleImpl will ignore
  • ExternalLoginModule will only succeed if configured with a suitable CredentialsSupport that ensures that authentication against the external IDP is successful.

Integration with Pre-Authentication and Login Module Chain

Example JAAS Configuration

  Example {
     your.org.PreAuthenticationLoginModule optional;
     org.apache.jackrabbit.oak.security.authentication.user.LoginModuleImpl optional;
     org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModule sufficient
                     sync.handlerName="your-synchandler_name"
                     idp.name="your_idp_name";
   };

See Pre-Authenticated Login for an example LoginModule that illustrates how the pre-authentication is being pushed to the shared stated.

Note: This configuration has been slightly adjusted from the example in OAK-3508 marking the pre-auth login to be optional. This highlights the fact that subsequent LoginModules are in charge of respecting the PreAuthenticatedLogin marker and properly populating the Subject in the second commit phase.

Also, in the example implementation the login never succeeds (in which case sufficient would actually work as well). However, if it ever succeeded the PreAuthenticatedLogin marker would be meaningless and the pre-auth module in fact would have to populate the Subject i.e. relying on details defined and handled by other LoginModules.

Understanding the Configuration

The LoginModule Sequence
  • The custom pre-auth module is in charge of handling custom pre-auth Credentials shared between the code performing the authentication outside of the scope of the repository and this module. It's only task is to create the PreAuthenticatedLogin marker and push it to the shared stated to inform subsequent modules, which will always be consulted due to the optional flag. - Login Success: not desired as we want subsequent modules to verify if there is a matching identity for the PreAuthenticatedLogin and later on populate the subject. - Login Failure: the default passing over the responsibility the other modules in the chain. - Commit: Nothing to do.

  • The LoginModuleImpl will try to resolve the repository user associated with the PreAuthenticatedLogin or perform regular login with the login Credentials if no PreAuthenticatedLogin is present. - Login Success: If there exists a valid user for the given PreAuthenticatedLogin or Credentials login will always succeed in case of a pre-auth login. Otherwise credentials are regularly evaluated (e.g. password validation). The authentication will continue down the chain due to the optional flag. - Login Failure: If no matching user exists or if the user is not valid (e.g. disabled). In case of regular authentication it will fail if the Credentials cannot be validated. Then authentication it will again continue down the LoginModule list. - Commit: If the login succeeded the login module will populate the Subject with Principals, Credentials and AuthInfo.

  • The ExternalLoginModule will try to resolve the PreAuthenticatedLogin or alternatively the Credentials to a SyncedIdentity. - If no SyncedIdentity exists the user is retrieved from external IDP and eventually synced into the repository. In case no PreAuthenticatedLogin is present retrieving identity additionally includes credentials validation. - If there exists a SyncedIdentity the module will validate it. In case of PreAuthenticatedLogin it checks if the identity needs to be synced again. - Login Success: If there exists a valid external identity on the IDP and it has be synced with the repository. - Login Failure: If no matching/valid identity exists on the IDP or if there exists a SyncedIdentity that doesn't belong to the IDP or we have a PreAuthenticatedLogin marker and the SyncedIdentity doesn't need a re-sync. - Commit: If the login succeeded the login module will populate the Subject with Principals, Credentials and AuthInfo.

Login with Different Credentials
Custom Pre-Auth Credentials
  • Custom pre-auth module will push PreAuthenticatedLogin on the shared state
  • Overall login suceeds if any of the subsequent modules is able to deal with the PreAuthenticatedLogin.
GuestCredentials
  • Custom pre-auth module will ignore
  • Overall login success if the subsequent modules allow for login with GuestCredentials
  • LoginModuleImpl by default supports GuestCredentials; success depends on the existence of a valid guest user in the repository.
  • ExternalLoginModule by default doesn't support GuestCredentials but may do if a suitable CredentialsSupport is configured.
SimpleCredentials
  • Custom pre-auth module will ignore
  • Overall login success if the subsequent modules allow for login with SimpleCredentials
  • LoginModuleImpl by default supports SimpleCredentials and it will succeed if the credentials are successfully validated against a local repository user.
  • ExternalLoginModule by default support SimpleCredentials and will succeed if authentication against the external IDP including sync is successful.
ImpersonationCredentials
  • Custom pre-auth module will ignore
  • Overall login success if the subsequent modules allow for login with ImpersonationCredentials
  • LoginModuleImpl by default supports ImpersonationCredentials and it will succeed if impersonation for the target user is allowed.
  • ExternalLoginModule by default doesn't support ImpersonationCredentials but may do if a suitable CredentialsSupport is configured.
Other Credentials
  • Overall login success only if the ExternalLoginModule supports these credentials
  • Custom pre-auth module will ignore
  • LoginModuleImpl will ignore
  • ExternalLoginModule will only succeed if configured with a suitable CredentialsSupport that ensures that authentication against the external IDP is successful.
FAQ
Why are the custom ‘PreAuthCredentials’ not public?

The custom Credentials shared between the code performing the authentication (outside of the repository) and the custom PreAuthenticationLoginModule implementation must neither be public nor shared with other implementations in order to prevent un-authenticated login.

Why is the ‘LoginModuleImpl’ not flagged SUFFICIENT?

If LoginModuleImpl was defined to be sufficient external identities would never be synced again if the PreAuthenticatedLogin marker is present in the shared state.

Why is the ‘ExternalLoginModule’ not flagged REQUIRED?

If ExternalLoginModule was required to succeed, login for local users was no longer possible. It also would mean that pre-authenticated login for a SyncedIdentity that doesn't needs a re-sync would not longer be possible and would ultimately fail the repository authentication.