You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by dclane <dc...@gmail.com> on 2008/12/05 22:57:18 UTC

Attempting WS-Security with Spring Security

I've successfully implemented Spring Security in my CXF project, but I really
need to get it hooked in with WS-Security to allow client applications to
authenticate.  (Spring Security is using HTTP form authentication right now,
which is fine in a web browser, but I need this to work for service
requests.)

I'm wanting to use UsernameToken authentication, with WS-Security passing
the authentication information on to Spring Security.  I've done a lot of
searching and it sounds easy enough when using the Spring Web Services
framework, but I don't know how it can be done in CXF.

I already have a simple WS-Security service and client working, I just don't
know how to integrate that with Spring Security.

Has anyone attempted this before?  Could someone give me a few pointers?  :)

Thank you,
 - Dave
-- 
View this message in context: http://www.nabble.com/Attempting-WS-Security-with-Spring-Security-tp20863276p20863276.html
Sent from the cxf-user mailing list archive at Nabble.com.


Re: Attempting WS-Security with Spring Security

Posted by Sergey Beryozkin <se...@progress.com>.
Hope you're having some progress with this effort.
After reading through the Spring Security docs, I think you need to have a custom Spring Security authorization manager/provider 
created which would implement one of the interfaces expected by SprongSecurity and also utilize a CXF-provided WS-Security 
UsernameToken handler (I'm presumimg it exists)...

What do you think ?

It would also be interesting to say, have a combined JAXWS/JAXRS service, which would use WS-Security on the SOAP side and 
XMLSecurity on the JAXRS side - I might fancy looking at such a demo/test at some time later on
Cheers, Sergey

>
> I've successfully implemented Spring Security in my CXF project, but I really
> need to get it hooked in with WS-Security to allow client applications to
> authenticate.  (Spring Security is using HTTP form authentication right now,
> which is fine in a web browser, but I need this to work for service
> requests.)
>
> I'm wanting to use UsernameToken authentication, with WS-Security passing
> the authentication information on to Spring Security.  I've done a lot of
> searching and it sounds easy enough when using the Spring Web Services
> framework, but I don't know how it can be done in CXF.
>
> I already have a simple WS-Security service and client working, I just don't
> know how to integrate that with Spring Security.
>
> Has anyone attempted this before?  Could someone give me a few pointers?  :)
>
> Thank you,
> - Dave
> -- 
> View this message in context: http://www.nabble.com/Attempting-WS-Security-with-Spring-Security-tp20863276p20863276.html
> Sent from the cxf-user mailing list archive at Nabble.com.
>
> 



Re: Attempting WS-Security with Spring Security

Posted by dclane <dc...@gmail.com>.
Alright, I've got a basic example working now.  I had to create a custom
interceptor to pass authentication information to Spring Security.  Here's
the code:

------- cxf.xml -------
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:security="http://www.springframework.org/schema/security"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:jaxrs="http://cxf.apache.org/jaxrs"
    xmlns:jaxws="http://cxf.apache.org/jaxws"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://cxf.apache.org/jaxrs
    http://cxf.apache.org/schemas/jaxrs.xsd
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-2.0.1.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
    http://cxf.apache.org/jaxws
    http://cxf.apache.org/schemas/jaxws.xsd">
    
    <import resource="classpath:META-INF/cxf/cxf.xml" />
    <import
resource="classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml"/> 
    <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
    
    <jaxws:endpoint id="auth"
implementor="com.company.auth.service.AuthServiceImpl"
address="/corporateAuth">
        <jaxws:inInterceptors>
            <bean
class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
                <constructor-arg>
                    <map>
                        <entry key="action" value="UsernameToken" />
                        <entry key="passwordType" value="PasswordText" />
                        <entry key="passwordCallbackClass"
value="com.company.auth.service.ServerPasswordCallback"/>
                    </map>
                </constructor-arg>
            </bean>
            <bean
class="com.company.service.web.auth.WSAuthenticationInterceptor">
                <property name="authenticationManager"
ref="authenticationManager"/>
            </bean>
        </jaxws:inInterceptors>
    </jaxws:endpoint>

    <security:authentication-manager alias="authenticationManager"/>
    <security:authentication-provider
user-service-ref="myUserDetailsService"/>
    <security:global-method-security secured-annotations="enabled"/>
    
    <bean id="springSecurityFilterChain"
class="org.springframework.security.util.FilterChainProxy">
        <security:filter-chain-map path-type="ant">
            <security:filter-chain pattern="/**"
filters="contextIntegrationFilter"/>
        </security:filter-chain-map>
    </bean>
    <bean id="contextIntegrationFilter"
class="org.springframework.security.context.HttpSessionContextIntegrationFilter"
/>
    
    <bean id="myUserDetailsService"
class="com.company.service.web.auth.AuthenticationDetailsService"/>
</beans>

------- WSAuthenticationInterceptor.java -------
package com.company.service.web.auth;

import java.util.Vector;

import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSSecurityEngineResult;
import org.apache.ws.security.WSUsernameTokenPrincipal;
import org.apache.ws.security.handler.WSHandlerConstants;
import org.apache.ws.security.handler.WSHandlerResult;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationManager;
import org.springframework.security.context.SecurityContextHolder;
import
org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.util.Assert;

public class WSAuthenticationInterceptor extends
AbstractPhaseInterceptor<SoapMessage> implements InitializingBean {

    private AuthenticationManager authenticationManager;

    public WSAuthenticationInterceptor() {

        super( Phase.POST_STREAM );
    }

    public void afterPropertiesSet() throws Exception {

        // ensure the 2 objects we need are not null
        Assert.notNull( authenticationManager, "Authentication Manager
should not be null!" );
    }

    public void handleMessage( SoapMessage message ) throws Fault {

        // get out the results from the message context
        Vector<WSHandlerResult> result = (Vector<WSHandlerResult>)
message.getContextualProperty( WSHandlerConstants.RECV_RESULTS );
        for (WSHandlerResult res : result) {

            // loop through security engine results
            for (WSSecurityEngineResult securityResult :
(Vector<WSSecurityEngineResult>) res.getResults()) {

                int action = securityResult.getAction();

                // determine if the action was a username token
                if ( ( action & WSConstants.UT ) > 0 ) {

                    // get the principal object
                    WSUsernameTokenPrincipal principal =
(WSUsernameTokenPrincipal) securityResult.getPrincipal();

                    Authentication authentication = new
UsernamePasswordAuthenticationToken( principal.getName(),
principal.getPassword() );
                    authentication = authenticationManager.authenticate(
authentication );

                    if ( !authentication.isAuthenticated() ) {
                        System.out.println( "This user is not authentic." );
                        //throw new AuthenticationException( "This user is
not authentic." );
                    }

                    SecurityContextHolder.getContext().setAuthentication(
authentication );
                }
            }
        }
    }

    /**
     * @return the authenticationManager
     */
    public AuthenticationManager getAuthenticationManager() {

        return authenticationManager;
    }

    /**
     * @param authenticationManager the authenticationManager to set
     */
    public void setAuthenticationManager( AuthenticationManager
authenticationManager ) {

        this.authenticationManager = authenticationManager;
    }

}

------- ServerPasswordCallback.java -------
package com.company.auth.service;

import java.io.IOException;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.ws.security.WSPasswordCallback;

public class ServerPasswordCallback implements CallbackHandler {

    public void handle( Callback[] callbacks ) throws IOException,
UnsupportedCallbackException {

        WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];

        // this seems ridiculous, but is necessary for passing
authentication on to Spring-Security.
        // we're essentially bypassing CXF's WSS4JInterceptor by ensuring
that the password callback always matches the client password.
        pc.setPassword( pc.getPassword() );
    }

}

I hope this is useful to someone else!  ;)
 - Dave


dclane wrote:
> 
> I've successfully implemented Spring Security in my CXF project, but I
> really need to get it hooked in with WS-Security to allow client
> applications to authenticate.  (Spring Security is using HTTP form
> authentication right now, which is fine in a web browser, but I need this
> to work for service requests.)
> 
> I'm wanting to use UsernameToken authentication, with WS-Security passing
> the authentication information on to Spring Security.  I've done a lot of
> searching and it sounds easy enough when using the Spring Web Services
> framework, but I don't know how it can be done in CXF.
> 
> I already have a simple WS-Security service and client working, I just
> don't know how to integrate that with Spring Security.
> 
> Has anyone attempted this before?  Could someone give me a few pointers? 
> :)
> 
> Thank you,
>  - Dave
> 

-- 
View this message in context: http://www.nabble.com/Attempting-WS-Security-with-Spring-Security-tp20863276p20902112.html
Sent from the cxf-user mailing list archive at Nabble.com.