CodeGym /Java Course /Module 5. Spring /Pre-authentication scripts

Pre-authentication scripts

Module 5. Spring
Level 18 , Lesson 6
Available

Examples include X.509, Siteminder, and authentication by the Java EE container in which the application runs. When using pre-authentication, Spring Security must:

  • Identify the user making the request.

  • Obtain permissions for the user.

The details will depend on the external authentication mechanism. The user can be identified by their certificate information in the case of X.509, or by the HTTP request header in the case of Siteminder. If you rely on container authentication, the user will be identified by calling the getUserPrincipal() method on the incoming HTTP request. In some cases, an external mechanism can provide information about the user's role/permissions, but in other cases, permissions must be obtained from a separate source, such as UserDetailsService.

Pre-authentication framework classes

Since most pre-authentication mechanisms follow the same pattern, Spring Security contains a set of classes that provide a back-end framework for implementing pre-authentication providers. This allows you to eliminate duplication and add new implementations in a structured way, without having to write everything from scratch. You don't need to know anything about these classes if you want to use something like X.509-based authentication, since it already provides a namespace configuration option that is easier to use and easier to get started with. If you need to use explicit bean configuration or plan to write your own implementation, then understanding how passed-in implementations work will be helpful. You can find the classes in org.springframework.security.web.authentication.preauth. We'll only give a general description here, so you should refer to the Javadoc and sources whenever needed.

AbstractPreAuthenticatedProcessingFilter

This class checks the current contents of the security context and, if empty, attempts to retrieve user information from the HTTP request and pass it to AuthenticationManager. Subclasses override the following methods to obtain this information:

Override AbstractPreAuthenticatedProcessingFilter
Java

protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request);
protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request);
Kotlin

protected abstract fun getPreAuthenticatedPrincipal(request: HttpServletRequest): Any?
protected abstract fun getPreAuthenticatedCredentials(request: HttpServletRequest): Any?

After calling them, the filter will create a PreAuthenticatedAuthenticationToken containing returned data, and will send it for authentication. By "authentication" here we really only mean further processing to possibly load the user's credentials, but while respecting the standard Spring Security authentication architecture.

Like other Spring Security authentication filters, the pre-authentication filter has a authenticationDetailsSource, which by default creates a WebAuthenticationDetails object to store additional information, such as the session ID and source IP address, in the details property of the Authentication object. In cases where user role information can be obtained from a pre-authentication mechanism, this information will also be stored in this property, taking into account information that implements the GrantedAuthoritiesContainer interface. This allows the authentication provider to read the credentials that have been allocated to the user externally. We'll look at a specific example next.

J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource

If the filter is configured with an authenticationDetailsSource that is an instance of this class, the credentials information is obtained by calling the isUserInRole(String role) for each "mapped role" from a predefined set. The class receives them from the configured MappableAttributesRetriever. Possible implementations include hard-coding the list in the application context and reading the role information from the information in the <security-role> section of the web.xml file. The sample pre-authentication application uses the latter approach.

There is an additional step where roles (or attributes) are mapped to GrantedAuthority objects from Spring Security via a configured Attributes2GrantedAuthoritiesMapper. By default, names are simply prefixed with the usual ROLE_ prefix, but this gives full control over the operating logic.

PreAuthenticatedAuthenticationProvider

The pre-authenticated provider only needs to load UserDetails object for the user. It does this by delegating authority to the AuthenticationUserDetailsService service. The latter is similar to the standard UserDetailsService, but accepts a Authentication object rather than just a username:


public interface AuthenticationUserDetailsService {
    UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException;
}

This interface may have other uses, but when pre-authenticated, it allows access to the credentials that have been packaged in the Authentication, which could be observed in the previous section. This is done by the PreAuthenticatedGrantedAuthoritiesUserDetailsService class. Alternatively, it can delegate authority to the standard UserDetailsService through the UserDetailsByNameServiceWrapper implementation.

Http403ForbiddenEntryPoint

AuthenticationEntryPoint is responsible for starting the authentication process for an unauthenticated user (if he is trying to access a protected resource), but does not apply in the case of pre-authentication. You can configure ExceptionTranslationFilter using an instance of this class only if you are not using pre-authentication in combination with other authentication mechanisms. It will be called if the user is rejected by AbstractPreAuthenticatedProcessingFilter, resulting in null authentication. Calling it always returns a response code of 403-forbidden.

Specific implementations

X.509-based authentication is described in a separate chapter. Here we'll look at some classes that provide support for other pre-authentication scenarios.

Request Header Authentication (Siteminder)

An external authentication system can pass information to the application by setting certain headers in the HTTP request . A good example of such a system is Siteminder, which passes the username in the SM_USER header. This mechanism is supported by the RequestHeaderAuthenticationFilter class, which simply extracts the username from the header. By default, the header name is SM_USER. For more information, see javadoc.

Note that when using a system like this, the framework does not perform any There are no authentication checks, so it is critical that the external system is properly configured to protect any access to the application. If an attacker can forge the headers in the original request in such a way that it cannot be detected, then he can choose any username at his discretion.

Example configuration using Siteminder

A typical configuration using this filter looks like this:


<security:http>
<!-- Additional http configuration omitted -->
<security:custom-filter position="PRE_AUTH_FILTER" ref="siteminderFilter" />
</security:http>
<bean id="siteminderFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
<property name="principalRequestHeader" value="SM_USER"/>
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService">
	<bean id="userDetailsServiceWrapper"
          class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
	<property name="userDetailsService" ref="userDetailsService"/>
	</bean>
</property>
</bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="preauthAuthProvider" />
</security:authentication-manager>

Here we have assumed that the security namespace is used for configuration. It also assumes that UserDetailsService has been added (named "userDetailsService") to the configuration to load user roles.

Java EE Container Level Authentication

Class The J2eePreAuthenticatedProcessingFilter will retrieve the username from the userPrincipal property for the HttpServletRequest. The use of this filter is typically combined with the use of Java EE roles, as described above in the J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource subsection.

The sample project has sample app that uses this approach, so grab the code from GitHub and look at the app context file if you're interested.

Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION