Tomcat – Web Application and REST services SSO in tomcat and spring-security

single-sign-onspring-securitytomcat

I am using two different web application deployed in the same tomcat instance. One of web application and another one is REST services. When user logged into the web application and calls the REST service, REST should authenticate with the user logged in using the web application. How can i implement SSO in tomcat> If anyone have implemented it, please help mw.

Update:
I have implemented the Spring Security and J2EEPreAuthentication mechanism in my first web application. THis application invokes the second application (REST services) using the DOJO (JavaScript Framework).

Update:
I have found the solution. Please read my answer below.

Best Answer

We can implement the SSO between traditional web application and non web based application like the RESTful web services. This example shows the sample code for implementing the SSO between web application and RESTful web services. The following is the configuration in the spring-security.xml file

<security:http create-session="never" use-expressions="true" 
                   auto-config="false" 
                   entry-point-ref="preAuthenticatedProcessingFilterEntryPoint" >

        <security:intercept-url pattern="/**" access="permitAll"/>
        <security:intercept-url pattern="/admin/**" access="hasRole('tomcat')"/>
        <security:intercept-url pattern="/**" access="hasRole('tomcat')"/>
        <security:custom-filter position="PRE_AUTH_FILTER" ref="preAuthFilter"/>
        <!-- Required for Tomcat, will prompt for username / password twice otherwise -->
        <security:session-management session-fixation-protection="none"/>
    </security:http>

    <bean id="preAuthenticatedProcessingFilterEntryPoint"
                class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/>

    <bean id="preAuthFilter"
                class="org.springframework.security.web.authentication.preauth.j2ee.J2eePreAuthenticatedProcessingFilter">
        <property name="authenticationManager" ref="appControlAuthenticationManager"/>
        <property name="authenticationDetailsSource"
                        ref="j2eeBasedPreAuthenticatedWebAuthenticationDetailsSource"/>
    </bean> 

    <security:authentication-manager alias="appControlAuthenticationManager">
        <security:authentication-provider ref="preAuthenticatedAuthenticationProvider"/>
    </security:authentication-manager>

    <bean id="preAuthenticatedAuthenticationProvider"
                class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
        <property name="preAuthenticatedUserDetailsService" ref="inMemoryAuthenticationUserDetailsService"/>
    </bean>

    <bean id="j2eeBasedPreAuthenticatedWebAuthenticationDetailsSource"
                class="org.springframework.security.web.authentication.preauth.j2ee.J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource">
        <property name="mappableRolesRetriever" ref="webXmlMappableAttributesRetriever"/>
        <property name="userRoles2GrantedAuthoritiesMapper" ref="simpleAttributes2GrantedAuthoritiesMapper"/>
    </bean>

    <bean id="webXmlMappableAttributesRetriever"
                class="org.springframework.security.web.authentication.preauth.j2ee.WebXmlMappableAttributesRetriever"/>

    <bean id="simpleAttributes2GrantedAuthoritiesMapper"
                class="org.springframework.security.core.authority.mapping.SimpleAttributes2GrantedAuthoritiesMapper">
        <property name="attributePrefix" value=""/>
    </bean>

    <bean id="inMemoryAuthenticationUserDetailsService"
                class="com.org.InMemoryAuthenticationUserDetailsService"/> 

The above code is in the web application. Also the same code can be in the REST project's spring security xml file. Add the following code into the web.xml file:

<security-constraint>
        <web-resource-collection>
            <web-resource-name>Wildcard means whole app requires authentication</web-resource-name>
            <url-pattern>/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>tomcat</role-name>
        </auth-constraint>

        <user-data-constraint>
            <!-- transport-guarantee can be CONFIDENTIAL, INTEGRAL, or NONE -->
            <transport-guarantee>NONE</transport-guarantee>
        </user-data-constraint>
    </security-constraint>
    <login-config>
        <auth-method>FORM</auth-method>
        <form-login-config>
            <form-login-page>/login.jsp</form-login-page>
            <form-error-page>/error.jsp</form-error-page>
        </form-login-config>
    </login-config>

The above code should be only in the normal web application. Then enable the SSO valve in the tomcat's server.xml file. Tomcat uses the cookie based SSO login. The session ids are stored in the cookies. If your browser disabled the cookie, then SSO will not work.

Hope this explanation helps.