2008-05-01 19:51:35 +00:00
|
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
2008-05-13 17:13:47 +00:00
|
|
|
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="preauth"
|
|
|
|
xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
|
|
<info>
|
|
|
|
<title>Pre-Authentication Scenarios</title>
|
|
|
|
</info>
|
|
|
|
<para> There are situations where you want to use Spring Security for authorization, but the user
|
|
|
|
has already been reliably authenticated by some external system prior to accessing the
|
|
|
|
application. We refer to these situations as <quote>pre-authenticated</quote> scenarios.
|
|
|
|
Examples include X.509, Siteminder and authentication by the J2EE container in which the
|
2009-10-08 14:14:40 +00:00
|
|
|
application is running. When using pre-authentication, Spring Security has to
|
|
|
|
<orderedlist><listitem><para>Identify the user making the request.
|
|
|
|
</para></listitem><listitem><para>Obtain the authorities for the
|
|
|
|
user.</para></listitem></orderedlist>The details will depend on the external authentication
|
|
|
|
mechanism. A user might be identified by their certificate information in the case of X.509, or
|
|
|
|
by an HTTP request header in the case of Siteminder. If relying on container authentication, the
|
|
|
|
user will be identified by calling the <methodname>getUserPrincipal()</methodname> method on the
|
|
|
|
incoming HTTP request. In some cases, the external mechanism may supply role/authority
|
|
|
|
information for the user but in others the authorities must be obtained from a separate source,
|
|
|
|
such as a <interfacename>UserDetailsService</interfacename>. </para>
|
2008-05-13 17:13:47 +00:00
|
|
|
<section>
|
|
|
|
<title>Pre-Authentication Framework Classes</title>
|
2009-10-08 14:14:40 +00:00
|
|
|
<para> Because most pre-authentication mechanisms follow the same pattern, Spring Security has a
|
|
|
|
set of classes which provide an internal framework for implementing pre-authenticated
|
|
|
|
authentication providers. This removes duplication and allows new implementations to be added
|
|
|
|
in a structured fashion, without having to write everything from scratch. You don't need to
|
|
|
|
know about these classes if you want to use something like <link xlink:href="#x509">X.509
|
|
|
|
authentication</link>, as it already has a namespace configuration option which is simpler
|
2009-12-28 13:59:21 +00:00
|
|
|
to use and get started with. If you need to use explicit bean configuration or are planning on
|
2009-10-08 14:14:40 +00:00
|
|
|
writing your own implementation then an understanding of how the provided implementations work
|
|
|
|
will be useful. You will find classes under the
|
|
|
|
<package>org.springframework.security.web.authentication.preauth</package>. We just provide
|
|
|
|
an outline here so you should consult the Javadoc and source where appropriate. </para>
|
2008-05-13 17:13:47 +00:00
|
|
|
<section>
|
|
|
|
<title>AbstractPreAuthenticatedProcessingFilter</title>
|
2009-10-08 14:14:40 +00:00
|
|
|
<para> This class will check the current contents of the security context and, if empty, it
|
|
|
|
will attempt to extract user information from the HTTP request and submit it to the
|
|
|
|
<interfacename>AuthenticationManager</interfacename>. Subclasses override the following
|
|
|
|
methods to obtain this information:
|
|
|
|
<programlisting language="java">
|
2008-05-13 17:13:47 +00:00
|
|
|
protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request);
|
2008-05-01 19:51:35 +00:00
|
|
|
|
2008-05-13 17:13:47 +00:00
|
|
|
protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request);
|
|
|
|
</programlisting>
|
2009-10-08 14:14:40 +00:00
|
|
|
After calling these, the filter will create a
|
|
|
|
<classname>PreAuthenticatedAuthenticationToken</classname> containing the returned data
|
|
|
|
and submit it for authentication. By <quote>authentication</quote> here, we really just mean
|
|
|
|
further processing to perhaps load the user's authorities, but the standard Spring Security
|
|
|
|
authentication architecture is followed. </para>
|
2008-05-13 17:13:47 +00:00
|
|
|
</section>
|
|
|
|
<section>
|
|
|
|
<title>AbstractPreAuthenticatedAuthenticationDetailsSource</title>
|
2009-10-08 14:14:40 +00:00
|
|
|
<para> Like other Spring Security authentication filters, the pre-authentication filter has an
|
|
|
|
<literal>authenticationDetailsSource</literal> property which by default will create a
|
|
|
|
<classname>WebAuthenticationDetails</classname> object to store additional information
|
|
|
|
such as the session-identifier and originating IP address in the <literal>details</literal>
|
|
|
|
property of the <interfacename>Authentication</interfacename> object. In cases where user
|
|
|
|
role information can be obtained from the pre-authentication mechanism, the data is also
|
|
|
|
stored in this property. Subclasses of
|
|
|
|
<classname>AbstractPreAuthenticatedAuthenticationDetailsSource</classname> use an extended
|
|
|
|
details object which implements the
|
|
|
|
<interfacename>GrantedAuthoritiesContainer</interfacename> interface, thus enabling the
|
|
|
|
authentication provider to read the authorities which were externally allocated to the user.
|
|
|
|
We'll look at a concrete example next. </para>
|
2008-05-15 17:00:45 +00:00
|
|
|
<section xml:id="j2ee-preauth-details">
|
2008-05-13 17:13:47 +00:00
|
|
|
<title>J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource</title>
|
2009-10-08 14:14:40 +00:00
|
|
|
<para> If the filter is configured with an <literal>authenticationDetailsSource</literal>
|
|
|
|
which is an instance of this class, the authority information is obtained by calling the
|
|
|
|
<methodname>isUserInRole(String role)</methodname> method for each of a pre-determined
|
|
|
|
set of <quote>mappable roles</quote>. The class gets these from a configured
|
|
|
|
<interfacename>MappableAttributesRetriever</interfacename>. Possible implementations
|
|
|
|
include hard-coding a list in the application context and reading the role information
|
|
|
|
from the <literal><security-role></literal> information in a
|
|
|
|
<filename>web.xml</filename> file. The pre-authentication sample application uses the
|
|
|
|
latter approach. </para>
|
|
|
|
<para>There is an additional stage where the roles (or attributes) are mapped to Spring
|
|
|
|
Security <interfacename>GrantedAuthority</interfacename> objects using a configured
|
|
|
|
<interfacename>Attributes2GrantedAuthoritiesMapper</interfacename>. The default will
|
|
|
|
just add the usual <literal>ROLE_</literal> prefix to the names, but it gives you full
|
|
|
|
control over the behaviour. </para>
|
2008-05-13 17:13:47 +00:00
|
|
|
</section>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
|
|
<title>PreAuthenticatedAuthenticationProvider</title>
|
2009-10-08 14:14:40 +00:00
|
|
|
<para> The pre-authenticated provider has little more to do than load the
|
|
|
|
<interfacename>UserDetails</interfacename> object for the user. It does this by delegating
|
|
|
|
to a <interfacename>AuthenticationUserDetailsService</interfacename>. The latter is similar
|
|
|
|
to the standard <interfacename>UserDetailsService</interfacename> but takes an
|
|
|
|
<interfacename>Authentication</interfacename> object rather than just user name:
|
|
|
|
<programlisting language="java">
|
2008-05-13 17:13:47 +00:00
|
|
|
public interface AuthenticationUserDetailsService {
|
|
|
|
UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException;
|
|
|
|
}
|
2009-10-08 14:14:40 +00:00
|
|
|
</programlisting>
|
|
|
|
This interface may have also other uses but with pre-authentication it allows access to the
|
|
|
|
authorities which were packaged in the <interfacename>Authentication</interfacename> object,
|
|
|
|
as we saw in the previous section. The
|
|
|
|
<classname>PreAuthenticatedGrantedAuthoritiesUserDetailsService</classname> class does
|
|
|
|
this. Alternatively, it may delegate to a standard
|
|
|
|
<interfacename>UserDetailsService</interfacename> via the
|
|
|
|
<classname>UserDetailsByNameServiceWrapper</classname> implementation. </para>
|
2008-05-13 17:13:47 +00:00
|
|
|
</section>
|
|
|
|
<section>
|
2009-05-12 05:37:11 +00:00
|
|
|
<title>Http403ForbiddenEntryPoint</title>
|
2009-10-08 14:14:40 +00:00
|
|
|
<para> The <interfacename>AuthenticationEntryPoint</interfacename> was discussed in the <link
|
|
|
|
xlink:href="#tech-intro-auth-entry-point">technical overview</link> chapter. Normally it
|
|
|
|
is responsible for kick-starting the authentication process for an unauthenticated user
|
|
|
|
(when they try to access a protected resource), but in the pre-authenticated case this
|
|
|
|
doesn't apply. You would only configure the
|
|
|
|
<classname>ExceptionTranslationFilter</classname> with an instance of this class if you
|
|
|
|
aren't using pre-authentication in combination with other authentication mechanisms. It will
|
|
|
|
be called if the user is rejected by the
|
|
|
|
<classname>AbstractPreAuthenticatedProcessingFilter</classname> resulting in a null
|
|
|
|
authentication. It always returns a <literal>403</literal>-forbidden response code if
|
|
|
|
called. </para>
|
2008-05-13 17:13:47 +00:00
|
|
|
</section>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
|
|
<title>Concrete Implementations</title>
|
2009-10-08 14:14:40 +00:00
|
|
|
<para> X.509 authentication is covered in its <link xlink:href="#x509">own chapter</link>. Here
|
|
|
|
we'll look at some classes which provide support for other pre-authenticated scenarios. </para>
|
2008-05-15 17:00:45 +00:00
|
|
|
<section>
|
|
|
|
<title>Request-Header Authentication (Siteminder)</title>
|
2009-10-08 14:14:40 +00:00
|
|
|
<para> An external authentication system may supply information to the application by setting
|
2009-12-28 13:59:21 +00:00
|
|
|
specific headers on the HTTP request. A well known example of this is Siteminder, which
|
2009-10-08 14:14:40 +00:00
|
|
|
passes the username in a header called <literal>SM_USER</literal>. This mechanism is
|
|
|
|
supported by the class <classname>RequestHeaderAuthenticationFilter</classname> which simply
|
|
|
|
extracts the username from the header. It defaults to using the name
|
|
|
|
<literal>SM_USER</literal> as the header name. See the Javadoc for more details. </para>
|
2008-05-15 17:00:45 +00:00
|
|
|
<tip>
|
2009-10-08 14:14:40 +00:00
|
|
|
<para>Note that when using a system like this, the framework performs no authentication
|
|
|
|
checks at all and it is <emphasis>extremely</emphasis> important that the external system
|
|
|
|
is configured properly and protects all access to the application. If an attacker is able
|
|
|
|
to forge the headers in their original request without this being detected then they could
|
2009-12-28 13:59:21 +00:00
|
|
|
potentially choose any username they wished. </para>
|
2008-05-15 17:00:45 +00:00
|
|
|
</tip>
|
2008-06-08 18:53:22 +00:00
|
|
|
<section>
|
|
|
|
<title>Siteminder Example Configuration</title>
|
2009-10-08 14:14:40 +00:00
|
|
|
<para> A typical configuration using this filter would look like this: <programlisting><![CDATA[
|
2009-11-14 15:20:19 +00:00
|
|
|
<security:http>
|
|
|
|
<!-- Additional http configuration omitted -->
|
|
|
|
<security:custom-filter ref="siteminderFilter" />
|
|
|
|
</security:http>
|
|
|
|
|
2009-06-07 21:00:50 +00:00
|
|
|
<bean id="siteminderFilter" class=
|
2009-10-08 14:14:40 +00:00
|
|
|
"org.springframework.security.web.authentication.preauth.header.RequestHeaderAuthenticationFilter">
|
2008-06-08 18:53:22 +00:00
|
|
|
<property name="principalRequestHeader" value="SM_USER"/>
|
|
|
|
<property name="authenticationManager" ref="authenticationManager" />
|
|
|
|
</bean>
|
|
|
|
|
|
|
|
<bean id="preauthAuthProvider"
|
2009-06-07 21:00:50 +00:00
|
|
|
class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
|
2008-06-08 18:53:22 +00:00
|
|
|
<property name="preAuthenticatedUserDetailsService">
|
|
|
|
<bean id="userDetailsServiceWrapper"
|
2009-07-08 14:53:40 +00:00
|
|
|
class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
|
2008-06-08 18:53:22 +00:00
|
|
|
<property name="userDetailsService" ref="userDetailsService"/>
|
|
|
|
</bean>
|
|
|
|
</property>
|
|
|
|
</bean>
|
|
|
|
|
2009-11-14 15:20:19 +00:00
|
|
|
<security:authentication-manager alias="authenticationManager">
|
|
|
|
<security:authentication-provider ref="preauthAuthProvider" />
|
|
|
|
</security-authentication-manager>
|
2008-06-08 18:53:22 +00:00
|
|
|
]]>
|
2009-10-08 14:14:40 +00:00
|
|
|
</programlisting> We've assumed here that the security namespace is being used for
|
|
|
|
configuration (hence the user of the <literal>custom-filter</literal>,
|
|
|
|
<literal>authentication-manager</literal> and
|
|
|
|
<literal>custom-authentication-provider</literal> elements (you can read more about them
|
|
|
|
in the <link xlink:href="ns-config">namespace chapter</link>). You would leave these out
|
|
|
|
of a traditional bean configuration. It's also assumed that you have added a
|
|
|
|
<interfacename>UserDetailsService</interfacename> (called
|
|
|
|
<quote>userDetailsService</quote>) to your configuration to load the user's roles.
|
2008-06-08 18:53:22 +00:00
|
|
|
</para>
|
|
|
|
</section>
|
2008-05-15 17:00:45 +00:00
|
|
|
</section>
|
|
|
|
<section>
|
|
|
|
<title>J2EE Container Authentication</title>
|
2009-10-08 14:14:40 +00:00
|
|
|
<para> The class <classname>J2eePreAuthenticatedProcessingFilter</classname> will extract the
|
|
|
|
username from the <literal>userPrincipal</literal> property of the
|
2009-12-28 13:59:21 +00:00
|
|
|
<interfacename>HttpServletRequest</interfacename>. Use of this filter would usually be
|
2009-10-08 14:14:40 +00:00
|
|
|
combined with the use of J2EE roles as described above in <xref
|
|
|
|
linkend="j2ee-preauth-details"/>. </para>
|
|
|
|
<para> There is a sample application in the codebase which uses this approach, so get hold of
|
|
|
|
the code from subversion and have a look at the application context file if you are
|
|
|
|
interested. The code is in the <filename>samples/preauth</filename> directory. </para>
|
2008-05-15 17:00:45 +00:00
|
|
|
</section>
|
2008-05-13 17:13:47 +00:00
|
|
|
</section>
|
|
|
|
</chapter>
|