incubator-sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Sling Website > Authentication
Date Wed, 06 Jan 2010 13:47:00 GMT
<html>
<head>
    <base href="http://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/1519/1/1/_/styles/combined.css?spaceKey=SLINGxSITE&amp;forWysiwyg=true"
type="text/css">
    </head>
<body style="background-color: white" bgcolor="white">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
     <h2><a href="http://cwiki.apache.org/confluence/display/SLINGxSITE/Authentication">Authentication</a></h2>
     <h4>Page <b>edited</b> by             <a href="http://cwiki.apache.org/confluence/display/~fmeschbe">Felix
Meschberger</a>
    </h4>
     
          <br/>
     <div class="notificationGreySide">
         <h1><a name="Authentication-Authentication"></a>Authentication</h1>



<div>
<ul>
    <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>
</ul></div>

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

<ol>
	<li>Extract credentials from the request</li>
	<li>Login to the JCR repository
<sup id='FootnoteMarker2'>
    <a name='FootnoteMarker2'
        href='#Footnote2'
        onClick='footnoteHighlight("2",true);'
        alt='Footnote: Click here to display the footnote'
        title='Footnote: Click here to display the footnote'
        class='FootnoteMarker'>
            2
    </a>
</sup>
.</li>
</ol>


<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>

<ul>
	<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>
class.</li>
	<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>
</ul>


<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='http://cwiki.apache.org/confluence/download/attachments/115813/authentication.png'><img
src="/confluence/download/thumbnails/115813/authentication.png" align="absmiddle" border="0"
title="Request Processing" /></a></p></td>
<td class="confluenceTd" valign="top">
<ol>
	<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>
</ol>
</td></tr></tbody></table>

<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>SlingAuthenticator.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>org.apache.sling.engine</tt>
bundle, which also has the <tt>SlingMainServlet</tt>. In fact the single instance
of this class is managed by the <tt>SlingMainServlet</tt>. The <tt>SlingAuthenticator</tt>
class has the following basic features:</p>

<ul>
	<li>The <tt>authenticate</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>SlingAuthenticator.authenticate</tt> method can either admit the request
as an anonymous request or request authentication from the client by calling its own <tt>login</tt>
method.</li>
	<li>The <tt>login</tt> method, which implements the <tt>login</tt>
method of the <tt>Authenticator</tt> interface also selects an <tt>AuthenticationHandler</tt>
service appropriate for the request. But this time, the <tt>AuthenticationHandler.requestAuthentication</tt>
method is called, 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>authenticate</tt> and <tt>login</tt>
methods to the appropriate <tt>AuthenticationHandler</tt></li>
</ul>



<p>The <tt>authenticate</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>
<tr>
<th class='confluenceTh'> Attribute </th>
<th class='confluenceTh'> Description </th>
</tr>
<tr>
<td class='confluenceTd'> <tt>javax.jcr.Session</tt> </td>
<td class='confluenceTd'> The JCR Session. This attribute is used by the <tt>SlingMainServlet</tt>
to create the <tt>ResourceResolver</tt> to be provided in the <tt>SlingHttpServletRequest.getResourceResolver</tt>
method. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>org.osgi.service.http.authentication.remote.user</tt>
</td>
<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>
</tr>
<tr>
<td class='confluenceTd'> <tt>org.osgi.service.http.authentication.type</tt>
</td>
<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>
</tr>
</tbody></table>

<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 Engine 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);
</pre>
</div></div>

<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 the 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>
<tr>
<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>
</tr>
</tbody></table>

<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>
<tr>
<td class='confluenceTd'> URL part </td>
<td class='confluenceTd'> Scheme </td>
<td class='confluenceTd'> Host/Port </td>
<td class='confluenceTd'> Path </td>
</tr>
<tr>
<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>
</tr>
<tr>
<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>
</tr>
<tr>
<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>
</tr>
</tbody></table>

<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="https://issues.apache.org/jira/browse/SLING-938" 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>org.apache.sling.engine.auth.Authenticator</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);

}
</pre>
</div></div>

<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>
<tr>
<th class='confluenceTh'> Exit State </th>
<th class='confluenceTh'> Description </th>
</tr>
<tr>
<td class='confluenceTd'> Normal </td>
<td class='confluenceTd'> An <tt>AuthenticationHandler</tt> could be selected
to which the login request could be forwarded. </td>
</tr>
<tr>
<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>
</tr>
<tr>
<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.
</td>
</tr>
</tbody></table>



<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>
  </thead>
  <tbody>
    <tr name='Footnote2'>
      <td valign='top' class='FootnoteNum' headings='footnote-th1'>
        <a href='#FootnoteMarker2'
          onClick='footnoteMarkerHighlight("2");'
          onMouseOver='footnoteHighlight("2",false);'
          alt='Footnote: Click to return to reference in text'
          title='Footnote: Click to return to reference in text'
          id='FootnoteNum2'>
            2
        </a>
      </td>
      <td id='Footnote2'
        valign='top'
        width='100%'
        class='Footnote'
        headings='footnote-th2'>
          Currently the credentials are always verified by trying to login to the JCR repository.
Once an <a href="http://cwiki.apache.org/SLING/add-resourceresolverfactory-service-interface.html"
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>
      </td>
    </tr>
  </tbody>
</table></p>
     </div>
     <div id="commentsSection" class="wiki-content pageSection">
       <div style="float: right;">
            <a href="http://cwiki.apache.org/confluence/users/viewnotifications.action"
class="grey">Change Notification Preferences</a>
       </div>

       <a href="http://cwiki.apache.org/confluence/display/SLINGxSITE/Authentication">View
Online</a>
       |
       <a href="http://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=115813&revisedVersion=10&originalVersion=9">View
Change</a>
              |
       <a href="http://cwiki.apache.org/confluence/display/SLINGxSITE/Authentication?showComments=true&amp;showCommentArea=true#addcomment">Add
Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message