jeudi 19 février 2015

Spring security custom SSO + client in the same domain

Before pasting code I'm going to explain how my scenario is:


1# Spring Security Web App which manages a user database (user, roles, groups). It has a login page which allows users log in with user/password or OpenID.


2# Servlet 3.0 Web App which delegates security to Tomcat basic, takes data and authorize based on the same database shared through JNDI.


Requisites are transform 1# in a SSO Application and allow 2# to redirect to 1# login page instead of using basic, perform login and come back. Then, authenticate the user in 2# through the cookie provided in 1#.


Both apps are in the same domain.


I went through this taking the following aproach:


1- Implement in 1# Spring's remember me service to persist the cookie. To achieve this I followed some tutorials. To simplify, I added the remember me to the applicationContext-security.xml:



<security:remember-me key="myappkey" services-ref="rememberMeServices" />


And I implemented the rememberMeServices



<bean id="rememberMeServices" class="com.example.myapp.security.CustomRememberMeServices">
<constructor-arg index="0" value="myappkey"/>
<constructor-arg index="1" ref="customUserDetailsService"/>
<constructor-arg index="2" ref="jdbcTokenRepository" />
<property name="useSecureCookie" value="false" />
</bean>


And also my own AuthenticationSuccessHandler to redirect to 2# after successful authentication:



<bean id="customAuthenticationSuccessHandler" class="com.example.myapp.security.CustomAuthenticationSuccess">
<property name="defaultTargetUrl" value="/user/home"/>
</bean>


Obviously, I've created a table to save token,series, etc. from cookies.


I've implemented my own PersistentTokenBasedRememberMeServices in order to avoid the setCookie behaviour which sets the cookie path to the app context.


This is my approach:



public class CustomRememberMeServices extends PersistentTokenBasedRememberMeServices{

@Autowired
UserDetailsServiceImpl userDetailsService;


public CustomRememberMeServices(String key, UserDetailsService userDetailsService, PersistentTokenRepository tokenRepository) {
super(key, userDetailsService, tokenRepository);
}

@Override
protected void setCookie(String[] tokens, int maxAge, HttpServletRequest request, HttpServletResponse response) {
String cookieValue = encodeCookie(tokens);
Cookie cookie = new Cookie(getCookieName(), cookieValue);
cookie.setMaxAge(maxAge);
cookie.setDomain(request.getServerName());
cookie.setPath("/");
cookie.setSecure(false);
cookie.setHttpOnly(false);
response.addCookie(cookie);
}

@Override
protected void cancelCookie(HttpServletRequest request, HttpServletResponse response) {
Cookie cookie = new Cookie(getCookieName(), null);
cookie.setMaxAge(0);
cookie.setPath("/");
response.addCookie(cookie);
}

}


In 2# I'm thinking in integrating Spring security because I think there is no possibility to manage this with servlet and tomcat (Am I wrong?).


The flow is this:


I go to a protected resource in 2#, 2# redirects me to the 1# login page, I successfully log in 1#, the remember me cookie is generated and I come back to 2# automatically.


This works as expected. The problem is in the last step. The request does not come with any cookie from 1# so the user can't be authenticated. I suspect that the browser is not considering to send the cookies because maybe for the browser are in different domains? I've checked this through a filter in 2#. Neither principal nor cookies are in the request.


Additionally, I don't know how to afford authentication in 2#. Do I use PRE_AUTH, siteminder, implement the same remember me service or do it without spring?


Answers will be voted and I promise to accept the correct answer.


Aucun commentaire:

Enregistrer un commentaire