Pre-Authentication Scenarios 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 pre-authenticated scenarios.
Examples include X.509, Siteminder and authentication by the J2EE container in which the
application is running. When using pre-authentication, Spring Security has to Identify the user making the request. Obtain the authorities for the user.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 getUserPrincipal() 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 UserDetailsService. Pre-Authentication Framework Classes 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 X.509 authentication, as it already has a namespace
configuration option which is simpler to use and get started with. If you need to use
explicit bean configuration or are planning on writing your own implementation then an
understanding of how the provided implementations work will be useful. You will find
classes under the
org.springframework.security.web.authentication.preauth. We just
provide an outline here so you should consult the Javadoc and source where appropriate. AbstractPreAuthenticatedProcessingFilter 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 AuthenticationManager. Subclasses override the
following methods to obtain this information:
protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request);
protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request);
After calling these, the filter will create a
PreAuthenticatedAuthenticationToken containing the returned
data and submit it for authentication. By authentication here, we
really just mean further processing to perhaps load the user's authorities, but the
standard Spring Security authentication architecture is followed. Like other Spring Security authentication filters, the pre-authentication filter
has an authenticationDetailsSource property which by default will
create a WebAuthenticationDetails object to store additional
information such as the session-identifier and originating IP address in the
details property of the
Authentication object. In cases where user role
information can be obtained from the pre-authentication mechanism, the data is also
stored in this property, with the details implementing the
GrantedAuthoritiesContainer interface. This
enables the authentication provider to read the authorities which were externally
allocated to the user. We'll look at a concrete example next. J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource If the filter is configured with an
authenticationDetailsSource which is an instance of this
class, the authority information is obtained by calling the
isUserInRole(String role) method for each of a
pre-determined set of mappable roles. The class gets these from a
configured MappableAttributesRetriever. Possible
implementations include hard-coding a list in the application context and
reading the role information from the <security-role>
information in a web.xml file. The pre-authentication
sample application uses the latter approach.There is an additional stage where the roles (or attributes) are mapped to
Spring Security GrantedAuthority objects using a
configured Attributes2GrantedAuthoritiesMapper.
The default will just add the usual ROLE_ prefix to the
names, but it gives you full control over the behaviour. PreAuthenticatedAuthenticationProvider The pre-authenticated provider has little more to do than load the
UserDetails object for the user. It does this by
delegating to a AuthenticationUserDetailsService. The
latter is similar to the standard UserDetailsService
but takes an Authentication object rather than just
user name:
public interface AuthenticationUserDetailsService {
UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException;
}
This interface may have also other uses but with pre-authentication it allows access
to the authorities which were packaged in the
Authentication object, as we saw in the previous
section. The
PreAuthenticatedGrantedAuthoritiesUserDetailsService class
does this. Alternatively, it may delegate to a standard
UserDetailsService via the
UserDetailsByNameServiceWrapper implementation. Http403ForbiddenEntryPoint The AuthenticationEntryPoint was discussed in the
technical overview 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
ExceptionTranslationFilter 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
AbstractPreAuthenticatedProcessingFilter resulting in a null
authentication. It always returns a 403-forbidden response code
if called. Concrete Implementations X.509 authentication is covered in its own chapter.
Here we'll look at some classes which provide support for other pre-authenticated
scenarios. Request-Header Authentication (Siteminder) An external authentication system may supply information to the application by
setting specific headers on the HTTP request. A well known example of this is
Siteminder, which passes the username in a header called SM_USER.
This mechanism is supported by the class
RequestHeaderAuthenticationFilter which simply extracts the
username from the header. It defaults to using the name SM_USER
as the header name. See the Javadoc for more details. Note that when using a system like this, the framework performs no
authentication checks at all and it is extremely 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 potentially choose any
username they wished. Siteminder Example Configuration A typical configuration using this filter would look like this:
]]>
We've assumed here that the security namespace
is being used for configuration. It's also assumed that you have added a
UserDetailsService (called
userDetailsService) to your configuration to load the user's
roles. J2EE Container Authentication The class J2eePreAuthenticatedProcessingFilter will
extract the username from the userPrincipal property of the
HttpServletRequest. Use of this filter would usually
be combined with the use of J2EE roles as described above in . 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 samples/preauth
directory.