HowToDoInJava

  • Python
  • Java
  • Spring Boot
  • Dark Mode
Home / Spring Security / Spring Security Siteminder Pre-authentication Example

Spring Security Siteminder Pre-authentication Example

So far we have learned about securing spring application using login form based security, custom user details security and many more such security related concepts. In this post, I am giving an example of scenario where use is already authenticated via any third party application or tool e.g. site minder which is very common interface between multiple applications in a group.

In this scenario, user has been pre-authenticated in any other application and get into your web application using site minder. Site minder sends a request header about pre-authenticated user which you can utilize to further authorize the user inside your application. You do not need to further authenticate the user, just verify user roles from database and provide appropriate access inside application.

Please keep in mind that site minder is only for example, in fact you can use any third party
application to get pre-authenticated user. Only request header will change in each case.

Lets follow the tutorial step by step.

Step 1) Maven dependency

I am using maven for runtime dependencies so giving pom.xml. If you are using ANT then download respective JARs and add them in class path.

<properties>
	<spring.version>3.0.5.RELEASE</spring.version>
	<jackson-mapper-asl.version>1.9.9</jackson-mapper-asl.version>
    <jaxb-api.version>2.2.7</jaxb-api.version>
  </properties>
  <dependencies>
    <!-- Spring 3 dependencies -->
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-core</artifactId>
		<version>${spring.version}</version>
		<scope>runtime</scope>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-web</artifactId>
		<version>${spring.version}</version>
		<scope>runtime</scope>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-webmvc</artifactId>
		<version>${spring.version}</version>
		<scope>runtime</scope>
	</dependency>
	<!-- Spring Security -->
	<dependency>
	    <groupId>org.springframework.security</groupId>
	    <artifactId>spring-security-core</artifactId>
	    <version>${spring.version}</version>
	    <type>jar</type>
	    <scope>runtime</scope>
	</dependency>
	<dependency>
	    <groupId>org.springframework.security</groupId>
	    <artifactId>spring-security-web</artifactId>
	    <version>${spring.version}</version>
	    <type>jar</type>
	    <scope>runtime</scope>
	</dependency>
	<dependency>
	    <groupId>org.springframework.security</groupId>
	    <artifactId>spring-security-config</artifactId>
	    <version>${spring.version}</version>
	    <type>jar</type>
	    <scope>runtime</scope>
	</dependency>
	<dependency>
	    <groupId>org.springframework.security</groupId>
	    <artifactId>spring-security-taglibs</artifactId>
	    <version>${spring.version}</version>
	    <type>jar</type>
	    <scope>runtime</scope>
	</dependency>
  </dependencies>

Step 2) Update web.xml file

There is nothing much in web.xml file. Just add context config location and spring security related filter mappings.

<web-app>
  <display-name>www.howtodoinjava.com</display-name>
  
  	<servlet>
		<servlet-name>spring-mvc</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
 
	<servlet-mapping>
		<servlet-name>spring-mvc</servlet-name>
		<url-pattern>/*</url-pattern>
	</servlet-mapping>
 
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring-mvc-servlet.xml</param-value>
	</context-param>
	
	<filter>
	    <filter-name>springSecurityFilterChain</filter-name>
	    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	</filter>
	<filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
 
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
</web-app>

Step 3) Spring security configuration

This is most important step because here we will configure the pre authentication security related mappings. Lets look at the file:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:security="http://www.springframework.org/schema/security"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/beans/ http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/context/ http://www.springframework.org/schema/context/spring-context-2.5.xsd
        http://www.springframework.org/schema/aop/ http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
        http://www.springframework.org/schema/security/ http://www.springframework.org/schema/security/spring-security-3.0.3.xsd">
     
     <!-- Annotation are configuring the application -->
     <mvc:annotation-driven/>
	
     <!-- Scan this package for all config annotations -->
	<context:component-scan base-package="com.howtodoinjava.web" />
	
	<security:http use-expressions="true" auto-config="false" entry-point-ref="http403EntryPoint">
    	<!-- Additional http configuration omitted -->
    	<security:intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
    	<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="customUserDetailsService"/>
	      	</bean>
	    </property>
    </bean>

    <security:authentication-manager alias="authenticationManager">
      	<security:authentication-provider ref="preauthAuthProvider" />
    </security:authentication-manager>	
    
    <bean id="customUserDetailsService" class="com.howtodoinjava.security.CustomUserDetailsService"></bean>
    <bean id="http403EntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"></bean>
    
</beans>

Lets understand this configuration:

  1. “mvc:annotation-driven” is used to tell spring that it needs to scan the annotations in base package specified in “context:component-scan” for searching the resource mappings.
  2. “security:http” configuration specifies security related configuration and options. “use-expressions” tells that while matching the “access” property in “security:intercept-url”, expressions are allowed and should be parsed.
  3. “security:custom-filter” specifies definition of a custom filter which will be invoked to verify user’s validity.
  4. PRE_AUTH_FILTER assures that this filter will be invoked before other authentication/authorization handling. I have defined a siteminder filter for this. You can name it to another name.
  5. “principalRequestHeader” is important because it is the request header attribute which will be checked once user come to application from another application. So, ask this header from third party provider to integrate here.
  6. “authenticationManager” is ultimately using “customUserDetailsService” which I have written in “com.howtodoinjava.security.CustomUserDetailsService” class. This class implements UserDetailsService interface and have one method loadUserByUsername(). This method must return a authenticated user interface of type “org.springframework.security.core.userdetails.UserDetails“. This object will have other authorization details such as user role, which will be used in further security.

Step 4) Write custom UserDetailsService class

This class will get the username passed from third party application and username is passed as request header e.g. in our case “SM_USER“.

package com.howtodoinjava.security;

import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

public class CustomUserDetailsService implements UserDetailsService
{
	public UserDetails loadUserByUsername(String username)
	        throws UsernameNotFoundException, DataAccessException
    {
		System.out.println("username recieved :: " + username);
		@SuppressWarnings("deprecation")
		
		//Get this user details from database and set its roles also here
		
		UserDetails user = new User(username, "password", true, true, true, true,
				new GrantedAuthority[]{ new GrantedAuthorityImpl("ROLE_USER") });
		return user;
    }
}

Step 5) Write secured resources to verify

I ave written two very basic classes for sake of simplicity. I will try to access them with and without request header “SM_USER“.

DemoController.java

package com.howtodoinjava.web;

@Controller
@RequestMapping("/users")
public class DemoController 
{
	@RequestMapping(method = RequestMethod.GET, value="/{id}", headers="Accept=application/xml")
	public @ResponseBody User getUserById(@PathVariable String id) 
	{
		User user = new User();
		user.setFirstName("john");
		user.setLastName("adward");
		return user;
	}
	
	@RequestMapping(method = RequestMethod.GET,  headers="Accept=application/xml")
	public @ResponseBody Users getAllUsers() 
	{
		User user1 = new User();
		user1.setFirstName("john");
		user1.setLastName("adward");
		
		User user2 = new User();
		user2.setFirstName("tom");
		user2.setLastName("hanks");
		
		Users users = new Users();
		users.setUsers(new ArrayList<User>());
		users.getUsers().add(user1);
		users.getUsers().add(user2);
		
		return users;
	}
}

Users.java

@XmlRootElement(name="users")
@XmlAccessorType(XmlAccessType.NONE)
public class Users 
{
	@XmlElement(name="user")
	private Collection<User> users;

	public Collection<User> getUsers() {
		return users;
	}

	public void setUsers(Collection<User> users) {
		this.users = users;
	}
}

User.java

@XmlRootElement(name="user")
@XmlAccessorType(XmlAccessType.NONE)
public class User {
	
	@XmlElement(name="first-name")
	private String firstName;
	
	@XmlElement(name="last-name")
	private String lastName;
	
	public String getFirstName() {
		return firstName;
	}
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}
	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
}

Step 6) Demo

Lets deploy the application in tomcat server and test it.

Case 1 :: Without “SM_USER” request header

This will throw following exception:

org.springframework.security.web.authentication.preauth.PreAuthenticatedCredentialsNotFoundException: SM_USER header not found in request.
	at org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter.getPreAuthenticatedPrincipal(RequestHeaderAuthenticationFilter.java:43)
	at org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter.doAuthenticate(AbstractPreAuthenticatedProcessingFilter.java:98)
	at org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter.doFilter(AbstractPreAuthenticatedProcessingFilter.java:86)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:169)
	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
Spring security pre-authentication error
Spring security pre-authentication error

Case 2 :: With “SM_USER” request header

This time user will be able to access the resource.

Spring security pre-authentication success
Spring security pre-authentication success

To download the sourcecode of above tutorial, please follow below download link.

Sourcecode Download[/download]

Happy Learning !!

Was this post helpful?

Let us know if you liked the post. That’s the only way we can improve.
TwitterFacebookLinkedInRedditPocket

About Lokesh Gupta

A family guy with fun loving nature. Love computers, programming and solving everyday problems. Find me on Facebook and Twitter.

Feedback, Discussion and Comments

  1. Chenhai

    May 28, 2019

    What if user get authenticated through siteminder then they purposely modified the sm_user or jwt token. There is nothing we can do to prevent this only by reducing the token life time. Any better ideas?

  2. Vivek

    October 5, 2018

    What if I want to add a controller level authrization like

    @PreAuthorize(“hasRole(‘VIEW_LIST’)”)

    pn controller method.It does not seem working

    • Lokesh Gupta

      October 5, 2018

      It is applicable on method level only. Please refer to PreAuthorize Java docs.

  3. Susheela

    April 27, 2016

    but loadUserByUsername method is getting called only during server startup..
    If I need to call this method during login time for every other user after authentication by some third party, then what I need to do.??
    Please help me in this…

  4. Avanish Shah

    April 23, 2016

    1 Very Important update:
    In Method:
    UserDetails loadUserByUsername(String username){}

    For this method to be used in Dao class, You must write annotation: @Transactional(readOnly = true)
    Otherwise It will not work.
    Reference link:
    https://stackoverflow.com/questions/26984481/own-springsecurity-userdetailsservice-dont-load-user-could-not-obtain-transact

    Well, thanks alot for your work.

  5. Thales

    January 26, 2016

    Hi,

    Perfect article, but one question.

    In my class CustomUserDetailsService, I have one System.out.println(“username recieved :: ” + username); but it never print nothing, is it normal?

    Thanks

    • Lokesh Gupta

      January 27, 2016

      No, it should. Try a log statement. May be you are missing system console in your IDE.

  6. Diwakar

    December 10, 2015

    How do we retrieve the ROLES and all? As I can see loadbyUserName method is called which has only username.. so is there any way I can get those as well?

  7. nityananda

    November 11, 2015

    Hi Lokesh,
    can you please post a example of spring security with with sso .

  8. RAJ

    June 4, 2015

    Hi,
    I have have a rest services that is calling ODM. But now we are having siteminder for single sign on and it is not able to make a call to ODM. I am planning of change the connection code to support that single sign on. Can you please let me know how can I change my connection code so that it suport single sign on using siteminder.

  9. Swapnil

    March 27, 2015

    In my case,I have authenticated the user and created auth token using sha hashing technique.when after user tries to access specific url,I am using this auth token to identify the user and then authorize it for the accessed URL.My concern was repeated DB calls,first for authentication and then authorization.Since my app is REST based,it doesn’t maintain client state on server side.So,for every request,I have to make one DB call just for authorization.Is there any way to avoid these may DB calls?

    • Lokesh Gupta

      March 28, 2015

      HI Swapnil, being stateless is main feature of REST, and I will not advise to violate this rule. REST says that each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of “any stored context” on the server.
      To make things faster, however you can use server-side DB cache (e.g. ehcache) which will improve performance.

      • Swapnil

        March 28, 2015

        What if I send user authorities in auth token as well, and use them for all future requests?I guess this will be in accordance with REST paradigm without any performance cost(I am using SSL for all request and auth header will be encrypted at all times).

        • Lokesh Gupta

          March 28, 2015

          Requests can be manipulated using tools.. no matter how you encrypt it. NEVER rely on your client for security related things. Always crosscheck them in server before giving access to protected resources.

        • karthik

          April 23, 2015

          you do it by encrypting the user+roles.. the client request will have a token like userAbc.roleA-branchB-roleC-etc.#!@!@!encrypted-hashed-of-userAbc.roleA-branchB@~!@~

          The key to this encryption (or a salt if you hash it) is with server side, so client cannot tamper it..

  10. Pavan Sandeep

    November 13, 2014

    Very Good Article. I have a question :
    What if the Siteminder is sending extra headers like FIRST_NAME, LAST_NAME, USER_GROUPS etc. ? and we want to store them in our custom UserDetails object. At what point can I get the headers ? Do I need to write a custom filter extending the RequestHeaderAuthFilter and grab the extra headers from HttpServletRequest and add it to credentials property in Authentication class ? Or is there a nifty way that I can do it inside loadUserByUserName method ?

    • AK

      August 21, 2017

      were you able to find the solution on how to grab extra header details ?

  11. Mohit

    October 24, 2014

    I may not have understood the complete context of above implementation, but if the user is pre-authenticated using Siteminder or SSO, why you still need to create a UserDetails object with username and password.

    I have a application where i just need to create roles based on request headers passed to the application from SSO enabled server and want to use those roles in JSP file using spring security tags. Is it possible?

  12. vinayakbhadage

    October 8, 2014

    Thank you lokesh.. This is really helpful 🙂

  13. Vikas Vasnik

    July 14, 2014

    Hello Lokesh Nice Example, I want to implement SiteMinder Auth but there is already one application in tomcat container doing that,in similar fashion I want to do it for another app so what are the classes and process should be follow is it same or something different in Spring MVC .

    • Lokesh Gupta

      July 14, 2014

      Without knowing what your other application does and how it uses siteminder, I cannot make any statement.. for obvious reasons.

  14. Benoit

    May 9, 2014

    Thanks for this great tutorial. Just a quick note, you can use ‘new SimpleGrantedAuthority(“ROLE_USER”)’ instead of using the deprecated class ‘new GrantedAuthorityImpl(“ROLE_USER”)’.

    • Lokesh Gupta

      May 9, 2014

      Thanks for suggestion.

  15. MV

    May 7, 2014

    Lokesh, My application has already implemented form login and now, we are trying to add SSO through pre auth filter. I am not able to figure out the configuration syntax both form login filter and pre auth filter. Can you please guide me on this?

    • Lokesh Gupta

      May 7, 2014

      You should be using configuration from here as well: https://howtodoinjava.com/spring-security/login-form-based-spring-3-security-example/

      Magic will happen in SecurityInterceptor class you will write. There you will check if user was successfully authenticated SSO or not? If not then redirect him to login page.

  16. T.L.

    March 24, 2014

    Thank you for the great tutorial. I do have a foolish question but hopefully you can answer it. How is the SM_USER being set. I am able to generate the error when it is not set, but I do not see how you passed ‘demo’ to the the SM_USER. Could you please explain?

    • Lokesh Gupta

      March 24, 2014

      If you see in the image after section “Case 2 :: With “SM_USER” request header”, I am passing the request header “SM_USER” and set it’s value to “demo”. It is just like you pass “accept” o “content-type” request headers in your request. Basically, in configured environment, it will be passed by your thirdparty application through siteminder.

      • Atl

        August 19, 2014

        Hey Lokesh,
        Are you using any tool to do it or How are you setting up. Highly Appreciated if you can share the steps to do it. Thanks

        • Lokesh Gupta

          August 19, 2014

          I am not using any tool apart from RESTClient firefox plugin for testing the APIs.

  17. Abhishek Amte

    February 27, 2014

    Thanks alot. All of your examples were very helpful for me. I have a Spring application where I load my jsps and then through ajax calls interact with rest services. I need to secure both of these, but with basic auth there is no logout/custom login for MVC. Now my configuration is follows – on the server I have two authentications defined in the xml basic for pattern /rest/** and form based for /**. How should I pass username and password for each request for REST services?

    • Lokesh Gupta

      February 27, 2014

      For me, it’s very bad idea to send username and password in each request. Authenticate once and then use something else everytime (e.g. jsessionid or IP of authenticated user or any encrypted cookie stored in client system).

      But, if still you want to pass parameters, you can use something like this:

      $.ajax( {
      url : '/rest/user',
      dataType : 'json',
      beforeSend : function(xhr) {
      var bytes = Crypto.charenc.Binary.stringToBytes(username + ":" + password);
      var base64 = Crypto.util.bytesToBase64(bytes);
      xhr.setRequestHeader("Authorization", "Basic " + base64);
      },
      error : function(xhr, ajaxOptions, thrownError) {
      //handle error
      },
      success : function(model) {
      //
      }
      });

      Reference: https://code.google.com/archive/p/crypto-js

      • Abhishek Amte

        February 27, 2014

        Thanks alot. Yeah I know its a bad idea. I need the basic auth for REST services used by mobile apps, and form-based for web. Can u suggest me some good solution and point me to the right resources for that

        • Lokesh Gupta

          February 27, 2014

          Mobile Apps: No idea.
          Using Scripting: Above jquey ajax call will give you a base.
          Using normal html forms: See “JAX-RS Security” section in https://howtodoinjava.com/restful-web-service/

          If above does not answer your query, please elaborate more on what you want to accomplish.

          • Abhishek Amte

            February 27, 2014

            My project already has REST services. And they work perfectly. And the website too works fine. The web controllers only serve empty jsp pages. And after the jsp pages are loaded, they make call to REST api and interact with the DB and get the data (This was one of the requirements). So I need security for both of them.

  18. Manjunath

    December 24, 2013

    Thanks Lokesh, this is a good example.
    My application already has a spring security form-based login, my requirement is if SM_USER is not present in http headers or is invalid it must allow form based login.

    Currently, what happening is if SM_USER is not present it through a internal error “SM_USER header not found in request”, in that case can we show them the login form to accept username and password and do normal login process ?

    • Lokesh Gupta

      December 24, 2013

      Yes, it should be done in this way.

      • Manjunath

        December 30, 2013

        Thanks…I solved this by adding
        This way if SM_USER is missing, it will not through the error instead continue to show login page.

        But now the scenario is that in my loadUserByUsername, i need to set session timeout for the authenticated user manually. and secondly, i need to redirect based on role. Can you please help how to do this.

      • Abraham

        August 19, 2014

        How to do this please help…

        • Abraham

          August 21, 2014

          Please help I need to have a approach where try SiteMinder first. if dont get then Use the login page /guest/login.htm to login. Appreciate if you can share the spring security config xml….. Thanks in advance

    • MV

      May 6, 2014

      Manjunath,

      I have been working on exact scenario you have described above. Could you please let me know, how you configured both form login filter and pre auth filter together in your application?

      Thanks

  19. Naresh

    August 13, 2013

    Thanks for the example.
    How do we manage session? and How do we implement Hibernate cache (1st & 2nd level)? when using spring pre-authentication

    • Idree

      October 18, 2013

      Have you ever done something when few resources are authenticated normally and some other resources are pre-authenticated?
      Let me know if you have done similar to this. Thanks!

      • Lokesh Gupta

        October 18, 2013

        Yes.

Comments are closed on this article!

Search Tutorials

Spring Security Tutorial

  • Security – Introduction
  • Security – Method Level Security
  • Security – Siteminder
  • Security – Login Form
  • Security – JSP taglibs
  • Security – jdbc-user-service
  • Security – UserDetailsService
  • Security – Basic Auth
  • Security – Junit Tests
  • @PreAuthorize and @Secured

Meta Links

  • About Me
  • Contact Us
  • Privacy policy
  • Advertise
  • Guest and Sponsored Posts

Recommended Reading

  • 10 Life Lessons
  • Secure Hash Algorithms
  • How Web Servers work?
  • How Java I/O Works Internally?
  • Best Way to Learn Java
  • Java Best Practices Guide
  • Microservices Tutorial
  • REST API Tutorial
  • How to Start New Blog

Copyright © 2020 · HowToDoInjava.com · All Rights Reserved. | Sitemap

  • Sealed Classes and Interfaces