User Authentication
Status: NOT IMPLEMENTED
Created: 14. March 2010
Author: fmeschbe
JIRA: –
References: Merging Sling API and Commons Auth API
Update: fmeschbe/27. September 2013
Update
This concept is not being implemented because in the meantime ResourceProviderFactory
services have been introduced which can be flagged as being mandatory and thus validate credentials from authentication handlers. One such implementation is the JCR Resource Provider which does exactly that and internally validates the credentials by create a JCR Session.
Introduction
With the recent introduction of the Commons Auth Bundle and the current approach to break apart the dependency on JCR API from the Commons Auth Bundle we are faced with an issue of how to authenticate an HTTP request user while at the same time not binding the authentication mechanism to any data repository.
In other words we have the following requirements:
- Extract user authentication information from HTTP requests and assert the identity of the requesting entity (remote user or application)
- Setup a connection to data repository on behalf of the authenticated user
Currently the Commons Auth bundle controls the complete process of extracting authentication information, asserting the identity and connecting to the repository:
- Authentication information extraction using
AuthenticationHandler
services - Asserting identity by using the authentication information to login to the JCR Repository resulting in a JCR Session.
- Connecting to the data repository by using the
JcrResourceResolverFactory
to create aResourceResolver
on top of the JCR Session.
The problem here is, that the Commons Auth bundle is tied into using the JCR Repository to assert identities and into the JcrResourceResolverFactory
to connect to the data repository.
These dependencies are not entirely optimal. So a first improvement might be for the Commons Auth bundle to validate any authentication and pass the validated authentication info on the ot Commons Auth client which then uses this data to create the connection:
- Commons Auth extracts authentication information using
AuthenticationHandler
services - Commons Auth asserts the identity using the authentication information to login to the JCR Repository
- Commons Auth returns the asserted authentication information to (say) the Sling Main Servlet which uses the
ResourceResolverFactory
to connect to the repository and return aResourceResolver
The drawback here is, that (a) Commons Auth is stilled tied into the JCR API and (b) JCR Sessions are created twice thus creating quite a considerable overhead.
Proposal
A new service API is defined supporting the validation of credentials:
public interface CredentialValidator { /** * Validates the credentials and returns an AuthenticationInfo * object representing the validated credentials. * The implementation may return a new object or the same as * passed as a parameter. If a new object is returned the * implementation may copy some or all properties from the * passed in object. * The passed in AuthenticationInfo object should be considered * immutable by the implementation. * @param credentials The AuthenticationInfo representing the * credentials provided by the user in the HTTP request. * @return An AuthenticationInfo object representing the * validated credentials. * @throws LoginException if the passed credentials cannot * be validated. * @throws NullPointerException if credentials is null */ public AuthenticationInfo validate(AuthenticationInfo credentials) throws LoginException; }
The SlingAuthenticator
class makes use of the CredentialValidator
service to validate the credentials extracted by AuthenticationHandler
services. The returned AuthenticationInfo is then set as a request attribute.
The CredentialValidator
interface is implemented and registered as a service by the JCR based ResourceResolverFactory
implementation. The implementation of the method uses the credentials to authenticate with the JCR repository and returns an AuthenticationInfo object copied from the original object without the password but containing the JCR Session.
The SlingMainServlet
gets the AuthenticationInfo
object from the request attribute and passes it (as a Map
) to the ResourceResolverFactory.getResourceResolver(Map)
method to get the ResourceResolver
for the request.
The JCR based ResourceResolverFactory.getResourceResolver(Map)
knows about the CredentialValidator
implementation and can make use of the Session
object in the map to reuse the existing session.
Complete Steps Authenticating HTTP Requests
Requests are authenticated as follows:
- Client makes HTTP Request
- OSGi HTTP Service selects Sling to handle request and calls
HttpContext.handleSecurity
- Sling's
handleSecurity
method callsSlingAuthenticator.handleSecurity
- SlingAuthenticator extractes
AuthenticationInfo
by callingAuthenticationHandler.extractCredentials
- SlingAuthenticator passes
AuthenticationInfo
toCredentialValidator.validate
- (JCR based) CredentialValidator builds JCR Credentials from
AuthenticationInfo
and callsRepository.login
- CredentialValidator creates new AuthenticationInfo object copying all properties from input (except password) and setting the JCR
Session
as another property and returns - SlingAuthenticator sets new
AuthenticationInfo
as request attribute and sets remaining required request attributes and returns - Sling's
handleSecurity
returns successfully - OSGi HTTP Service passes control to
SlingMainServlet
- SlingMainServlet extracts
AuthenticationInfo
from request attribute and callsResourceResolverFactory.getResourceResolver
with thisAuthenticationInfo
(which actually extendsMap
) - (JCR based) ResourceResolverFactory recognizes the existing JCR Session and creates and returns a ResourceResolver based on this session
- SlingMainServlet continues request processing
- Finally SlingMainServlet closes the ResourceResolver at the end of request processing
Issues
The JCR based CredentialValidator
implementation creates a session, which may or may not be used and closed by users of the Sling Commons Auth AuthenticationSupport
service. A mechanism must be implemented to ensure Sessions placed into the AuthenticationInfo
by CredentialValidator
implementations are not left open and thus needlessly consume system resources.