|You can also check out this example to see the actual code involved in creating a custom security provider|
ModeShape can integrate with a custom authentication and authorization service, and it just takes a little bit of code.
ModeShape defines a simple interface for authenticating users. Each repository can have multiple providers, and a client is authenticated as soon as one of the providers accepts the credentials. The interface is quite simple:
All the parameters are supplied by ModeShape and contain everything necessary to authenticate a client attempting to create a new JCR Session.
Implementations are expected return a new ExecutionContext instance for the user, and this can be created from the repository's execution context by calling repositoryContext.with(securityContext), where securityContext is a custom implementation of the org.modeshape.jcr.security.SecurityContext interface that returns information about the authenticated user:
Note that if you want to provide authorization functionality, then your SecurityContext implementation must also implement AuthorizationProvider or AdvancedAuthorizationProvider.
ModeShape uses its org.modeshape.jcr.security.AuthorizationProvider interface to determine whether a Session has the appropriate privileges to perform reads and writes.
Simply have your SecurityContext implementation also implement this interface, and return true whenever the session is allows to perform the requested operations.
ModeShape uses its org.modeshape.jcr.security.AdvancedAuthorizationProvider interface to determine whether a Session has the appropriate privileges to perform reads and writes.
where Context is a new nested interface nested in AdvancedAuthorizationProvider:
Simply have your SecurityContext implementation also implement this interface, and return true whenever the session is allowed to perform the requested operations.
To have full control over the authentication & authorization process, you need to implement all the above interfaces and then configure your repository to use the AuthenticationProvider implementation.
Note how the authenticate method in the above example places this as the security context. This ensures that the hasPermission method will be called each time a repository operation is performed.
If you wanted more control, you could choose to implement AdvancedAuthorizationProvider instead of AuthorizationProvider.
Once you've implemented the interfaces and placed the classes on the classpath, all you have to do is then configure your repositories to use your authentication providers. As noted in the configuration overview, there is a nested document in the JSON configuration file in the "security" field, and this section lists the authentication provider implementations in the order that they should be used. For example:
This configuration enables the use of anonymous logins (although it disables a failed authentication attempt from downgrading to an anonymous session with the "useOnFailedLogin" as false), and configures two authentication providers: the MyAuthenticationProvider implementation will be used first, and if that does not authenticate the repository will delegate to the built-in JAAS provider. (Note that built-in providers can be referenced with an alias in the "classname" field rather than the fully-qualified classname.) Anonymous authentication is always performed last.