incubator-sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
Subject [CONF] Apache Sling Website > Authentication
Date Thu, 07 Jan 2010 15:03:00 GMT
    <base href="">
            <link rel="stylesheet" href="/confluence/s/1519/1/1/_/styles/combined.css?spaceKey=SLINGxSITE&amp;forWysiwyg=true"
<body style="background-color: white" bgcolor="white">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
     <h2><a href="">Authentication</a></h2>
     <h4>Page <b>edited</b> by             <a href="">Felix
     <div class="notificationGreySide">
         <h1><a name="Authentication-Authentication"></a>Authentication</h1>

    <li><a href='#Authentication-HttpContext.handleSecurity'>HttpContext.handleSecurity</a></li>
    <li><a href='#Authentication-SlingAuthenticator'>SlingAuthenticator</a></li>
    <li><a href='#Authentication-AuthenticationHandler'>AuthenticationHandler</a></li>
    <li><a href='#Authentication-Authenticator'>Authenticator</a></li>

<p>This page is about how requests are authenticated in Sling. The process of authenticating
client requests takes two steps:</p>

	<li>Extract credentials from the request</li>
	<li>Login to the JCR repository
<sup id='FootnoteMarker2'>
    <a name='FootnoteMarker2'
        alt='Footnote: Click here to display the footnote'
        title='Footnote: Click here to display the footnote'

<p>The first step is extensible by providing <tt>AuthenticationHandler</tt>
services, while the latter is coded into the <tt>SlingAuthenticator</tt> class.</p>

<p>But before getting to much into the details, lets step back and look at the various
actors in the authentication game:</p>

	<li>The <tt>SlingMaingServlet</tt> is the main entry point into the Sling
system for all request processing is registered with the OSGi HTTP Service. The servlet is
registered together with a customized implementation of the OSGi <tt>HttpContext</tt>
	<li>The <tt>HttpContext</tt> interface defines a <tt>handleSecurity</tt>
method which is intended to authenticate the request.</li>
	<li>The <tt>HttpContext.handleSecurity</tt> method is implemented in Sling
to use the <tt>AuthenticationSupport</tt> service.</li>
	<li>The <tt>AuthenticationSupport</tt> service is implemented in the Commons
Auth bundle and uses <tt>AuthenticationHandler</tt> services to extract credentials
from the request and login to the repository.</li>

<p>This sounds all very nice, but how is this linked together ? Lets look at the processing
steps from the point a request is sent to a Sling system to the moment the request is finally
entering the <tt>SlingMainServlet.service</tt> method:</p>

<table class="sectionMacro" border="0" cellpadding="5" cellspacing="0" width="100%"><tbody><tr>
<td class="confluenceTd" valign="top">
<p><a class="confluence-thumbnail-link 602x622" href=''><img
src="/confluence/download/thumbnails/115813/authentication.png" align="absmiddle" border="0"
title="Request Processing " /></a></p></td>
<td class="confluenceTd" valign="top">
	<li>First the OSGi HTTP Service implementation is analyzing the request URL to find
a match for a servlet or resource registered with the HTTP Service.</li>
	<li>Now the HTTP Service implementation has to call the <tt>handleSecurity</tt>
method of the <tt>HttpContext</tt> object with which the servlet or resource has
been registered. This method returns <tt>true</tt> if the request should be serviced.
If this method returns <tt>false</tt> the HTTP Service implementation terminates
the request sending back any response which has been prepared by the <tt>handleSecurity</tt>
method. Note, that the <tt>handleSecurity</tt> method must prepare the failure
response sent to the client, the HTTP Service adds nothing here. If the <tt>handleSecurity</tt>
method is successful, it must add two (or three) request attributes described below.</li>
	<li>When the <tt>handleSecurity</tt> method returns <tt>true</tt>
the HTTP Service either calls the <tt>Servlet.service</tt> method or sends back
the requested resource depending on whether a servlet or a resource has been selected in the
first step.</li>

<p>The important thing to note here is, that at the time the <tt>handleSecurity</tt>
method is called, the <tt>SlingMainServlet</tt> is not yet in control of the request.
So any functionality added by the <tt>SlingMainServlet</tt>, notably the <tt>SlingHttpServletRequest</tt>
and <tt>SlingHttpServletResponse</tt> objects are not available to the implementation
of the <tt>handleSecurity</tt> method.</p>

<h2><a name="Authentication-HttpContext.handleSecurity"></a>HttpContext.handleSecurity</h2>

<p>The <tt>HttpContext.handleSecurity</tt> method is implemented by the
<tt>SlingMainServlet</tt> because this servlet implements the <tt>HttpContext</tt>
interface itself. The <tt>handleSecurity</tt> method simply calls <tt>AuthenticationSupport.authenticate</tt>
method and returns the result of this call. If the call fails, an error is logged and <tt>false</tt>
is returned to not handle the request.</p>

<h2><a name="Authentication-SlingAuthenticator"></a>SlingAuthenticator</h2>

<p>The <tt>SlingAuthenticator</tt> class is an internal class of the <tt></tt>
bundle and implements the <tt>Authenticator</tt> and <tt>AuthenticationSupport</tt>

<p>The <tt>SlingAuthenticator</tt> class has the following basic features:</p>

	<li>The <tt>handleSecurity</tt> method selects an <tt>AuthenticationHandler</tt>
service appropriate for the request and calls the <tt>AuthenticationHandler.authenticate</tt>
method to extract the credentials from the request. If no credentials could be extracted,
the <tt>handleSecurity</tt> method can either admit the request as an anonymous
request or request authentication from the client by calling its own <tt>login</tt>
	<li>The <tt>login</tt> method selects an <tt>AuthenticationHandler</tt>
service appropriate for the request and calls the <tt>AuthenticationHandler.requestAuthentication</tt>
method, which is intended to send back to the client a response leading the client to provide
credentials. This may be a HTML form or it may be a plain 401/UNAUTHORIZED response status
to start HTTP authentication.</li>
	<li>The <tt>logout</tt> method selects an <tt>AuthenticationHandler</tt>
service appropriate for the request and calls the <tt>AuthenticationHandler.dropAuthentication</tt>
method, which is intended to send back to the client a response leading the client to provide
credentials. This may be a HTML form or it may be a plain 401/UNAUTHORIZED response status
to start HTTP authentication.</li>
	<li>Maintains an internal list of <tt>AuthenticationHandler</tt> services.
This list is consulted to forward the <tt>handleSecurity</tt>, <tt>login</tt>,
and <tt>logout</tt> methods to the appropriate <tt>AuthenticationHandler</tt></li>

<p>The <tt>handleSecurity</tt> method gets credentials from the <tt>AuthenticationHandler</tt>
and logs into the JCR repository using those credentials. If the login is successful, the
<tt>SlingAuthenticator</tt> sets the following request attributes:</p>

<table class='confluenceTable'><tbody>
<th class='confluenceTh'> Attribute </th>
<th class='confluenceTh'> Description </th>
<td class='confluenceTd'> <tt>org.osgi.service.http.authentication.remote.user</tt>
<td class='confluenceTd'> The user ID of the JCR Session. This attribute is used by
the HTTP Service implementation to implement the <tt>HttpServletRequest.getRemoteUser</tt>
method. </td>
<td class='confluenceTd'> <tt>org.osgi.service.http.authentication.type</tt>
<td class='confluenceTd'> The authentication type defined by the <tt>AuthenticationHandler</tt>.
This attribute is used by the HTTP Service implementation to implement the <tt>HttpServletRequest.getAuthType</tt>
method. </td>
<td class='confluenceTd'> <tt></tt>
<td class='confluenceTd'> The <tt>ResourceResolver</tt> created from the
credentials and the logged in JCR Session. This attribute may be used by servlets to access
the repository. Namely the <tt>SlingMainServlet</tt> uses this request attribute
to provide the <tt>ResourceResolver</tt> to handle the request. </td>
<td class='confluenceTd'> <tt>javax.jcr.Session</tt> </td>
<td class='confluenceTd'> The JCR Session. This attribute is from some level of backwards
compatibility. <b>Its use is deprecated and the attribute may be removed in future versions</b>.

<p><b>NOTE</b>: Do <em>NOT</em> use the <tt>javax.jcr.Session</tt>
request attribute in your Sling applications. This attribute must be considered an implementation
specific to convey the JCR Session to the <tt>SlingMainServlet</tt>. In future
versions of the Sling Commons Auth bundle, this request attribute may not be present anymore.
To get the JCR Session for the current request adapt the request's resource resolver to a
JCR Session:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
Session session = request.getResourceResolver().adaptTo(Session.class);

<p>Hint: If you want to know whether a request is authenticated or not, you can inspect
the result of the <tt>HttpServletRequest.getAuthType</tt> method: If this method
returns <tt>null</tt> the request is not authenticated.</p>

<h2><a name="Authentication-AuthenticationHandler"></a>AuthenticationHandler</h2>

<p>The <tt>AuthenticationHandler</tt> interface defines the service API
which may be implemented by authentication handlers registered as OSGi services. The <tt>AuthenticationHandler</tt>
services have a single required service registration property which is used to identify requests
to which the <tt>AuthenticationHandler</tt> service is applicable:</p>

<table class='confluenceTable'><tbody>
<td class='confluenceTd'> <tt>path</tt> </td>
<td class='confluenceTd'> One or more (array or vector) string values indicating the
request URLs to which the <tt>AuthenticationHandler</tt> is applicable. </td>

<p>Each path may be an absolute URL, an URL with just the host/port and path or just
a plain absolute path:</p>

<table class='confluenceTable'><tbody>
<td class='confluenceTd'> URL part </td>
<td class='confluenceTd'> Scheme </td>
<td class='confluenceTd'> Host/Port </td>
<td class='confluenceTd'> Path </td>
<td class='confluenceTd'> Absolute URL </td>
<td class='confluenceTd'> must match </td>
<td class='confluenceTd'> must match </td>
<td class='confluenceTd'> request URL path is prefixed with the path </td>
<td class='confluenceTd'> Host/Port with Path </td>
<td class='confluenceTd'> ignored </td>
<td class='confluenceTd'> must match </td>
<td class='confluenceTd'> request URL path is prefixed with the path </td>
<td class='confluenceTd'> Path </td>
<td class='confluenceTd'> ignored </td>
<td class='confluenceTd'> ignored </td>
<td class='confluenceTd'> request URL path is prefixed with the path </td>

<p>When looking for an <tt>AuthenticationHandler</tt> the authentication
handler is selected whose path is the longest match on the request URL. If the service is
registered with Scheme and Host/Port, these must exactly match for the service to be eligible.</p>

<p>The value of <tt>path</tt> service registration property value triggering
the call to any of the <tt>AuthenticationHandler</tt> methods is available as
the <tt>path</tt> request attribute (for the time of the method call only). If
the service is registered with multiple path values, the value of the <tt>path</tt>
request attribute may be used to implement specific handling.</p>

<h2><a name="Authentication-Authenticator"></a>Authenticator</h2>

<p>The <tt>Authenticator</tt> interface has been introduced in Rev. 768396
to implement <a href="" rel="nofollow">SLING-938
(Refine initiaition of the authentication process)</a>. This interface allows SLING
applications and error handlers to request the initiation of authentication.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader"
style="border-bottom-width: 1px;"><b></b></div><div
class="codeContent panelContent">
<pre class="code-java">
 * The &lt;code&gt;Authenticator&lt;/code&gt; <span class="code-keyword">interface</span>
defines the service <span class="code-keyword">interface</span> of the
 * authenticator used by the Sling engine. This service provides a method to
 * find an {@link AuthenticationHandler} and call its
 * {@link AuthenticationHandler#requestAuthentication(HttpServletRequest, HttpServletResponse)}
 * method.
 * &lt;p&gt;
 * This <span class="code-keyword">interface</span> is not intended to be implemented
by applications but may be
 * used to initiate the authentication process form a request processing servlet
 * or script.
 * @since 2.0.4
<span class="code-keyword">public</span> <span class="code-keyword">interface</span>
Authenticator {

     * Finds an {@link AuthenticationHandler} <span class="code-keyword">for</span>
the given request and call its
     * {@link AuthenticationHandler#requestAuthentication(HttpServletRequest, HttpServletResponse)}
     * method to initiate an authentication process with the client.
     * &lt;p&gt;
     * This method must be called on an uncommitted response since the
     * implementation may want to reset the response to start the authentication
     * process with a clean response. If the response is already committed an
     * &lt;code&gt;IllegalStateException&lt;/code&gt; is thrown.
     * &lt;p&gt;
     * After <span class="code-keyword">this</span> method has finished, request
processing should be terminated
     * and the response be considered committed and finished.
     * @param request The object representing the client request.
     * @param response The object representing the response to the client.
     * @<span class="code-keyword">throws</span> NoAuthenticationHandlerException
If no authentication handler
     *             claims responsibility to authenticate the request.
     * @<span class="code-keyword">throws</span> IllegalStateException If the
response has already been committed.
    <span class="code-keyword">public</span> void login(HttpServletRequest request,
            HttpServletResponse response);


<p>This interface is implemented by the <tt>SlingAuthenticator</tt> class
which is also registered under this service interface. The <tt>SlingAuthenticator</tt>
implementation in fact already has an implementation of this method, which finds an <tt>AuthenticationHandler</tt>
for the request and calls its <tt>requestAuthentication</tt> method.</p>

<p>The <tt>login</tt> method has three possible exit states:</p>

<table class='confluenceTable'><tbody>
<th class='confluenceTh'> Exit State </th>
<th class='confluenceTh'> Description </th>
<td class='confluenceTd'> Normal </td>
<td class='confluenceTd'> An <tt>AuthenticationHandler</tt> could be selected
to which the login request could be forwarded. </td>
<td class='confluenceTd'> <tt>NoAuthenticationHandlerException</tt> </td>
<td class='confluenceTd'> No <tt>AuthenticationHandler</tt> could be selected
to forward the login request to. In this case, the caller can proceed as appropriate. For
example a servlet, which should just login a user may send back a 403/FORBIDDEN status because
login is not possible. Or a 404/NOT FOUND handler, which tried to login as a fallback, may
continue and send back the regular 404/NOT FOUND response. </td>
<td class='confluenceTd'> <tt>IllegalStateException</tt> </td>
<td class='confluenceTd'> The response has already been committed and the login request
cannot be processed. Normally to request login, the current response must be reset and a new
response has to be prepared. This is only possible if the request has not yet been committed.

<p><table class='Footnotes' style='width: 100%; border:none;' cellspacing='0' cellpadding='0'
summary='This table contains one or more notes for references made elsewhere on the page.'>
  <caption class='accessibility'>Footnotes</caption>
  <thead class='accessibility'>
    <tr class='accessibility'>
      <th class='accessibility' id='footnote-th1'>Reference</th>
      <th class='accessibility' id='footnote-th2'>Notes</th>
    <tr name='Footnote2'>
      <td valign='top' class='FootnoteNum' headings='footnote-th1'>
        <a href='#FootnoteMarker2'
          alt='Footnote: Click to return to reference in text'
          title='Footnote: Click to return to reference in text'
      <td id='Footnote2'
          Currently the credentials are always verified by trying to login to the JCR repository.
Once an <a href=""
rel="nofollow">ResourceResolverFactory</a> API has been added, the process of logging
in is actualy replaced by a process of requesting a <tt>ResourceResolver</tt>
from the <tt>ResourceResolverFactory</tt>
     <div id="commentsSection" class="wiki-content pageSection">
       <div style="float: right;">
            <a href=""
class="grey">Change Notification Preferences</a>

       <a href="">View
       <a href="">View
       <a href=";showCommentArea=true#addcomment">Add

View raw message