Authentication : Implementation Details
General
Jackrabbit Oak covers different authentication requirements by providing default implementations and extension points for different setup scenarios.
Differences wrt Jackrabbit 2.x
See the corresponding documentation.
Authentication Requirements
Jackrabbit Oak covers the following login requirements and provides
dedicated LoginModule
implementation(s) for each scenario:
- Guest Login
- UserId/Password Login
- Impersonation Login
- Token Login
- Pre-Authenticated Login
- External Login
Guest Login
The proper way to obtain a guest session is specified by JSR 283:
String wspName = null; // or any other workspace name if not login to the default workspace
Session anonymous = repository.login(new GuestCredentials(), wspName);
As of Oak 1.0 Repository#login()
and Repository#login(null, wspName)
is no longer treated as guest login. This behavior of Jackrabbit-core is violating the specification, which defines that null-login should be used for those cases where the authentication process is handled outside the repository (see Pre-Authentication).
Similarly, any special treatment that Jackrabbit core applied for the guest (anonymous) user has been omitted altogether from the default LoginModuleImpl. By default, the built-in anonymous user will be created without any password. Therefore, explicitly uid/pw login using the anonymous userId will no longer work. This behavior is now consistent with the default login of any other user which doesn't have a password set.
GuestLoginModule
The aim of the GuestLoginModule implementation is to provide backwards compatibility
with Jackrabbit 2.x with respect to the guest (anonymous) login: the GuestLoginModule
can be added as optional entry to the chain of login modules in the JAAS (or
corresponding OSGi) configuration.
Example JAAS Configuration:
jackrabbit.oak {
org.apache.jackrabbit.oak.spi.security.authentication.GuestLoginModule optional;
org.apache.jackrabbit.oak.security.authentication.user.LoginModuleImpl required;
};
The behavior of the GuestLoginModule
is as follows:
Phase 1: Login
- tries to retrieve JCR credentials from the CallbackHandler using the CredentialsCallback
- in case no credentials could be obtained it pushes a new instance of GuestCredentials to the shared stated
and returns
true
- otherwise it returns
false
Phase 2: Commit
- if the phase 1 succeeded it will add the
GuestCredentials
created above andEveryonePrincipal
theSubject
in phase 2 of the login process and returnstrue
- otherwise it returns
false
UserId/Password Login
Oak 1.0 comes with 2 different login module implementations that can handle SimpleCredentials:
- Default (
LoginModuleImpl
) as described below ExternalLoginModule
as described in section External Authentication
LoginModuleImpl
The LoginModuleImpl defines a regular userId/password login and requires a
repository setup that supports User Management and is designed to
supports the following Credentials
:
SimpleCredentials
GuestCredentials
(see above)ImpersonationCredentials
(see below)
This login module implementations behaves as follows:
Phase 1: Login
- if a user does not exist in the repository (i.e. cannot be provided by the user manager) it returns
false
. - if an authorizable with the respective userId exists but is a group or a disabled users, it throws
LoginException
- if a user exists in the repository and the credentials don't match, it throws
LoginException
- if a user exists in the repository and the credentials match, it returns
true
- also, it adds the credentials to the shared state
- also, it adds the login name to the shared state
- also, it calculates the principals and adds them to the private state
- also, it adds the credentials to the private state
Phase 2: Commit
- if the private state contains the credentials and principals, it adds them (both) to the subject and returns
true
- if the private state does not contain credentials and principals, it clears the state and returns
false
User Authentication
The LoginModuleImpl
uses a configured Authentication
-implementation for
performing the login step. Which implementation to use is determined by the
UserAuthenticationFactory obtained by the given UserConfiguration
. It is
expected to provide an Authentication
implementation if the given
UserConfiguration
is accepted.
In case multiple implementations of the UserAuthenticationFactory
are available,
the precedence depends on its OSGi service ranking property. The default factory
implementation has a ranking of 0 (OSGi default). Services with the highest ranking
will take precedence.
See also section user management.
Impersonation Login
Another flavor of the Oak authentication implementation is covered by javax.jcr.Session#impersonate(Credentials)
, which allows to obtain a new Session
for a user identified by the specified credentials. As of JSR 333 this method can also be used in order to clone the existing session (i.e. self-impersonation of the user that holds the session).
With Oak 1.0 impersonation is implemented as follows:
Session#impersonate
takes any kind ofCredentials
- the specified credentials are wrapped in a new instance of ImpersonationCredentials
along with the current
AuthInfo
object. - these
ImpersonationCredentials
are passed toRepository.login
If impersonation succeeds consequently both depends on the authentication setup and on some implementation specific validation that make sure the editing session is allowed to impersonate the user identified by the credentials passed to the impersonate call.
With Oak 1.0 only the default login module (LoginModuleImpl) is able to deal
with ImpersonationCredentials
and applies the following logic:
- Self-Impersonation: Any attempt to impersonate the same session will succeed as long as the user is still valid (i.e. exists and has not been disabled).
- Regular Impersonation: Impersonation another user will only succeed if
the impersonated user is valid (i.e. exists and is not disabled) and the
user associated with the editing session is allowed to impersonate this
user. The latter depends on the User Management implementation
specifically on the return value of
User.getImpersonation().allows(Subject subject)
. See User Management : The Default Implementation for details.
ImpersonationCredentials
Since the implementation of Session.impersonate
no longer uses SimpleCredentials
to transport the original Subject
but rather performs the login with dedicated
ImpersonationCredentials, impersonation is no longer restricted to SimpleCredentials
being passed to Session#impersonate
call. Instead, the specified credentials are
passed to a new instance of ImpersonationCredentials
delegating the evaluation
and validation of the specified Credentials
to the configured login module(s).
This modification will not affect applications that used JCR API to impersonate
a given session. Note however that applications relying on the Jackrabbit
implementation and manually creating SimpleCredentials
with a
SecurityConstants.IMPERSONATOR_ATTRIBUTE
, would need to be refactored after
migration to Oak.
Impersonation with Custom Authentication Setup
Applications that wish to use a custom authentication setup need to ensure the following steps in order to get JCR impersonation working:
- Respect
ImpersonationCredentials
in the authentication setup. - Identify the impersonated from
ImpersonationCredentials.getBaseCredentials
and verify if it can be authenticated. - Validate that the editing session is allowed to impersonate: The user associated with the editing session can be identified by the AuthInfo obtained from
ImpersonationCredentials.getImpersonatorInfo()
.
Token Login
See section Token Authentication for details regarding token based authentication.
TokenLoginModule
The TokenLoginModule
is in charge of creating new login tokens and validate repository logins with TokenCredentials
. The exact behavior of this login module is described in section Token Authentication.
Pre-Authenticated Login
Oak provides two different mechanisms to create pre-authentication that doesn't involve the repositories internal authentication mechanism for credentials validation.
- Pre-Authentication combined with Login Module Chain
- Pre-Authentication without Repository Involvement (aka
null
login)
See section Pre-Authentication Login for further details and examples.
External Login
While the default setup in Oak is solely relying on repository functionality to ensure proper authentication it quite common to authenticate against different systems (e.g. LDAP). For those setups that wish to combine initial authentication against a third party system with repository functionality, Oak provides a default implementation with extension points:
- External Authentication: Summary of the external authentication and details about the
ExternalLoginModule
. - User and Group Synchronization: Details regarding user and group synchronization as well as a list of configuration options available with the default implementations present with Oak.
- Identity Management: Further information regarding external identity management.
- LDAP Integration: How to make use of the
ExternalLoginModule
with the LDAP identity provider implementation. This combination is aimed to replacecom.day.crx.security.ldap.LDAPLoginModule
, which relies on Jackrabbit internals and will no longer work with Oak.
ExternalLoginModule
The ExternalLoginModule is a base implementation that allows easy integration of 3rd party authentication and identity systems, such as LDAP. The general mode of the external login module is to use the external system as authentication source and as a provider for users and groups that may also be synchronized into the repository.
This login module implementation requires a valid SyncHandler and IdentityProvider to be present. The detailed behavior of the ExternalLoginModule
is described in section External Authentication.