incubator-sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Felix Meschberger (Confluence)" <conflue...@apache.org>
Subject [CONF] Apache Sling > Solving the Authentication Handler Credential Validation Problem
Date Fri, 27 Sep 2013 13:48:00 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/en/2176/1/1/_/styles/combined.css?spaceKey=SLING&amp;forWysiwyg=true"
type="text/css">
    </head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
    <h2><a href="https://cwiki.apache.org/confluence/display/SLING/Solving+the+Authentication+Handler+Credential+Validation+Problem">Solving
the Authentication Handler Credential Validation Problem</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~fmeschbe">Felix
Meschberger</a>
    </h4>
        <br/>
                         <h4>Changes (1)</h4>
                                 
    
<div id="page-diffs">
                    <table class="diff" cellpadding="0" cellspacing="0">
    
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >* Should a new session be retrieved
for each such access or should a long-running session be used which needs to be occasionally
refreshed ? <br>* Should mappings from user name to {{Subject}} be cached ? And how
is that cache refreshed ? <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">*
We must guard the use of the {{user.identified}} property somehow to prevent use of this feature
by code to get access to other user&#39;s data. <br></td></tr>
            <tr><td class="diff-unchanged" > <br>h3. Abstract Sling Repository
<br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <h1><a name="SolvingtheAuthenticationHandlerCredentialValidationProblem-SolvingtheAuthenticationHandlerCredentialValidationProblem"></a>Solving
the Authentication Handler Credential Validation Problem</h1>



<p>Status: DRAFT<br/>
Created: 27. September 2013<br/>
Author: fmeschbe<br/>
JIRA: &#8211;<br/>
References: &#8211;<br/>
Updated: &#8211;</p>


<div>
<ul>
    <li><a href='#SolvingtheAuthenticationHandlerCredentialValidationProblem-Problem'>Problem</a></li>
    <li><a href='#SolvingtheAuthenticationHandlerCredentialValidationProblem-Proposal'>Proposal</a></li>
    <li><a href='#SolvingtheAuthenticationHandlerCredentialValidationProblem-Implementations'>Implementations</a></li>
<ul>
    <li><a href='#SolvingtheAuthenticationHandlerCredentialValidationProblem-AuthenticationHandler'>Authentication
Handler</a></li>
    <li><a href='#SolvingtheAuthenticationHandlerCredentialValidationProblem-JCRResourceProvider'>JCR
Resource Provider</a></li>
    <li><a href='#SolvingtheAuthenticationHandlerCredentialValidationProblem-AbstractSlingRepository'>Abstract
Sling Repository</a></li>
</ul>
</ul></div>


<h2><a name="SolvingtheAuthenticationHandlerCredentialValidationProblem-Problem"></a>Problem</h2>

<p>There does not currently exist a good and transparent way for an Authentication Handler
to signal to the <tt>ResourceResovlerFactory</tt>, that the identity of a user
has been established and validated and that no further checks are required. For example an
SSO authentication handler will get the identity of a user provided by the SSO handler or
an OAuth 2 authentication handler proves the identity of the user by with the help of the
OAuth 2 provider.</p>


<h2><a name="SolvingtheAuthenticationHandlerCredentialValidationProblem-Proposal"></a>Proposal</h2>

<p>A new predefined property of the <tt>AuthenticationInfo</tt> map is defined
which can be set by the authentication handler to indicate that the user's identity has been
verified and can be guaranteed:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Default; brush: java; gutter: false" style="font-size:12px; font-family:
ConfluenceInstalledFont,monospace;">
public interface ResourceResolverFactory {
    ....
    /**
     * Name of the authentication information property used to indicate that the
     * identity of the user indicated by the {@link #USER} property has already
     * been validated by other means such as OAuth2, OpenID or similar SSO
     * functionality. As a consequence password-less access to a
     * {@link ResourceResolver} should be granted.
     * &lt;p&gt;
     * The non-empty string value of this property identifies the party having
     * validated the user's identity. It may be used by implementations of this
     * and the {@link ResourceProviderFactory} interfaces in log messages.
     * &lt;p&gt;
     * The type of this property, if present, is &lt;code&gt;String&lt;/code&gt;.
     *
     * @since 2.4 (bundle version 2.5.0)
     */
    String IDENTIFIED = "user.identified";
    ....
}
</pre>
</div></div>

<p><tt>ResourceProviderFactory</tt> services creating <tt>ResourceProvider</tt>
instances by establishing connections to the actual data store will leverage this flag to
implement a pre-authentication style of access.</p>


<h2><a name="SolvingtheAuthenticationHandlerCredentialValidationProblem-Implementations"></a>Implementations</h2>

<h3><a name="SolvingtheAuthenticationHandlerCredentialValidationProblem-AuthenticationHandler"></a>Authentication
Handler</h3>

<p>Implementations will just set the <tt>ResourceResolverFactory.IDENTIFIED</tt>
property in the Authentication Info map to the name of the authentication handler indicating
the identity has been validated.</p>

<p>This replaces mechanisms used today such has implementing a LoginModule service validating
a custom <tt>javax.jcr.Credentials</tt> instance.</p>


<h3><a name="SolvingtheAuthenticationHandlerCredentialValidationProblem-JCRResourceProvider"></a>JCR
Resource Provider</h3>

<p>The JCR Resource Provider will check for the property and create a <tt>Subject</tt>
used for establishing the session's owner:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Default; brush: java; gutter: false" style="font-size:12px; font-family:
ConfluenceInstalledFont,monospace;">
if (authenticationInfo.get("user.identified") != null) {

    // pre-identified user access
    final String userName = (String) authenticationInfo.get(ResourceResolverFactory.USER);
    final String identifier = (String) authenticationInfo.get("user.identified");

    log.info("getResourceProviderInternal: Logging in user {} identified by {}", userName,
identifier);
    Session tmp = null;
    try {
        tmp = session = repository.loginAdministrative(workspace);
        Authorizable auth = ((JackrabbitSession) tmp).getUserManager().getAuthorizable(userName);
        Subject s = new Subject();
        s.getPrincipals().add(auth.getPrincipal());
        session = Subject.doAs(s, new PrivilegedExceptionAction&lt;Session&gt;() {
            public Session run() throws Exception {
                return repository.login(workspace);
            }
        });
    } catch (PrivilegedActionException pae) {
        throw pae.getCause();
    } finally {
        if (tmp != null) {
            tmp.logout();
        }
    }
}
</pre>
</div></div>

<p>Considerations for creating the <tt>Subject</tt>:</p>

<ul>
	<li>Should the full <tt>Subject</tt> be created ? That is a subject which
contains the user's <tt>Principal</tt> as well as the full set of <tt>Principal</tt>
instances representing the set of groups of which the user is a member.</li>
	<li>Should only a simple <tt>Subject</tt> be created as in the example
above ? That is only the user's <tt>Principal</tt> is contained and the repository
implementation must then complete the set of <tt>Principals</tt> by the principals
for the groups.</li>
	<li>Should a dummy <tt>Subject</tt> be created which only contains a simple
<tt>Principal</tt> instance indicating the user's name (as opposed to the actual
<tt>Principal</tt> instance representing the actual repository principal) ?</li>
	<li>Should a new session be retrieved for each such access or should a long-running
session be used which needs to be occasionally refreshed ?</li>
	<li>Should mappings from user name to <tt>Subject</tt> be cached ? And
how is that cache refreshed ?</li>
	<li>We must guard the use of the <tt>user.identified</tt> property somehow
to prevent use of this feature by code to get access to other user's data.</li>
</ul>


<h3><a name="SolvingtheAuthenticationHandlerCredentialValidationProblem-AbstractSlingRepository"></a>Abstract
Sling Repository</h3>

<p>The Abstract Sling Repository implementation will need to fix the "<tt>null</tt>
Credentials" problem: Due to a misunderstanding the Abstract Sling Repository assumes anonymous
access to the repository if the <tt>Credentials</tt> to the login method is <tt>null</tt>
or missing. While this has been implemented like this in Jackrabbit it is actually not foreseen
by the specification. Rather missing or <tt>null</tt> Credentials indicate access
to the repository using pre-authentication where the <tt>Subject</tt> identifies
the owner of the <tt>Session</tt> to create.</p>

<p>So the Abstract Sling Repository implementation of the <tt>login(String, String)</tt>
method must be fixed along these lines:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Default; brush: java; gutter: false" style="font-size:12px; font-family:
ConfluenceInstalledFont,monospace;">
if (credentials == null) {
    if (Subject.getSubject(AccessController.getContext()) != null) {
        return getRepository().login(null, workspace);
    } else {
        // TODO: getAnonCredentials(this.anonUser) should not be used for anonymous access
        return getRepository().login(new GuestCredentials(), workspace);
    }
} else {
    return getRepository().login(credentials, workspace);
}
</pre>
</div></div>
    </div>
        <div id="commentsSection" class="wiki-content pageSection">
        <div style="float: right;" class="grey">
                        <a href="https://cwiki.apache.org/confluence/users/removespacenotification.action?spaceKey=SLING">Stop
watching space</a>
            <span style="padding: 0px 5px;">|</span>
                <a href="https://cwiki.apache.org/confluence/users/editmyemailsettings.action">Change
email notification preferences</a>
</div>
        <a href="https://cwiki.apache.org/confluence/display/SLING/Solving+the+Authentication+Handler+Credential+Validation+Problem">View
Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=34025061&revisedVersion=4&originalVersion=3">View
Changes</a>
                |
        <a href="https://cwiki.apache.org/confluence/display/SLING/Solving+the+Authentication+Handler+Credential+Validation+Problem?showComments=true&amp;showCommentArea=true#addcomment">Add
Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message