Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Integrate Single Sign On using Spring Security

I'm using Spring Security and I would like to use another site as one of my authentication providers. I have a basic form based login on my site. I want to have a link on my site that takes the user to an external site where they will login and that external site will then post a xml response back to me with data that I can verify to see if there was a successful login. Any help would be greatly appreciated!

  1. How do you integrate that flow into Spring Security?
  2. Once I get the response back, how would I auto log user on?

example using the guidance below:

filter (not shown my data is coming from xml off the request):

public class XMLAuthenticationFilter extends AbstractAuthenticationProcessingFilter{

    public XMLAuthenticationFilter() {
        super("/xml_security_check");
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request,
            HttpServletResponse response) throws AuthenticationException,
            IOException, ServletException {

            GrantedAuthority[] grantedAuthorities = new GrantedAuthority[] { new GrantedAuthorityImpl("ROLE_USER")};
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("userid", "pwd", grantedAuthorities);
            request.getSession();
            token.setDetails(new WebAuthenticationDetails(request));
            Authentication authenticatedUser = super.getAuthenticationManager().authenticate(token);
            SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
            request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());
            return authenticatedUser;

}

}

Auth Provider:

public class XMLAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider{
    private UserManager userManager;
    @Override
    protected void additionalAuthenticationChecks(UserDetails user, UsernamePasswordAuthenticationToken token) throws AuthenticationException {

    }

    @Override
    protected UserDetails retrieveUser(String userName, UsernamePasswordAuthenticationToken token) throws AuthenticationException {
        UserDetails user = userManager.getUser(userName); 
        if(user == null){
            Users newDCUser = new Users();
            newDCUser.setUserId(userName);
            newDCUser.setRawPassword((String) token.getCredentials());
            newDCUser.setFailedLoginAttempts(0);
            newDCUser.setBeginEffectiveDate(new Date());
            newDCUser.setEndEffectiveDate(getEffectiveDate());
            userManager.saveUser(newDCUser);
        }
        return userManager.loadUserByUsername(userName);
    }

    private Date getEffectiveDate(){
         Calendar calendar = Calendar.getInstance();
         calendar.add(Calendar.YEAR, 10);
         return calendar.getTime();
    }

    public UserManager getUserManager() {
        return userManager;
    }

    public void setUserManager(UserManager userManager) {
        this.userManager = userManager;
    }
}

bean config:

<bean id="xmlAuthenticationFilter" class="com.dc.api.service.impl.XMLAuthenticationFilter">
        <property name="authenticationManager" ref="am" />
    </bean>
    <bean id="xmlAuthenticationProvider" class="com.dc.api.service.impl.XMLAuthenticationProvider">
        <property name="userManager" ref="userManager"/>
    </bean>
like image 405
c12 Avatar asked Mar 19 '11 21:03

c12


People also ask

What is SSO in Spring Security?

Single sign-on (or SSO) allow users to use a single set of credentials to login into multiple related yet independent web applications. SSO also includes not asking users to login again into application B if they have already logged into application A given that A and B use SSO.

How OAuth2 works with SSO?

OAuth (Open Authorization) is an open standard for token-based authentication and authorization which is used to provide single sign-on (SSO). OAuth allows an end user's account information to be used by third-party services, such as Facebook, without exposing the user's password.


1 Answers

The general approach is:

1) Subclass AbstractAuthenticationToken for your XML logins, let's call it XMLAuthenticationToken.

2) Subclass AbstractAuthenticationProcessingFilter and add it to the filter chain after UsernamePasswordAuthenticationFilter. It should create a XMLAuthenticationToken based on the data in the XML. You can use UsernamePasswordAuthenticationFilter as an example for the general structure of the filter (that's most likely the filter that you are currently using for your regular Spring Security logins).

<http>
  <custom-filter after="FORM_LOGIN_FILTER" ref="xmlAuthenticationFilter"/>
</http>

The filter should set a filterProcessesUrl that is different from the UsernamePasswordFilter. This is the URL the external system will post the XML to. For example:

public XmlAuthenticationFilter() {
    super("/xml_security_check");
}

3) Subclass AbstractUserDetailsAuthenticationProvider. Have it look up the user from the UserDetailsService based on the info in the token, and then authenticate it. Use DaoAuthenticationProvider as an example. You will need to register the new provider with the AuthenticationManager.

<authentication-manager>
  <authentication-provider user-service-ref='myUserDetailsService'/>
  <authentication-provider ref="xmlAuthenticationProvider" />
</authentication-manager>

You might be able to get away with reusing UsernamePasswordAuthenticationToken (for #1, it has a nice "details" extension mechanism) and DaoAuthenticationProvider (or subclassing it) for #3.

like image 83
sourcedelica Avatar answered Oct 26 '22 15:10

sourcedelica