Good day,

I am dusting off my CXF after many years, trying to replace a Weblogic SAML 
implementation with CXF.

I’ve been trying out a WS-SecurityPolicy-described SAML invocation hello world 
using some of the CXF systest code as the basis of my example.   This is an 
asymmetric sender-vouches call.   

I’ve noticed that the WebServiceContext in the service, when I call 
getUserPrincipal() always returns me the x509 signature  subject for the 
message (alice), and never the SAML Subject Name that’s created on the client 
callback (uid=sts-client,o=mock-sts.com <http://mock-sts.com/>).  

Is this as designed?  Looking at the WSS4J and CXF code, I have seen code paths 
that do create a Principal based on the SAML Subject but it seems this never 
gets called if the signature principal is already set.  I’ve tried a variety of 
approaches but my unfamiliarity with CXF is showing.      

My only current thought is that I could workaround this by turning off token 
validation and building a custom JAAS SAML Login Module that validates the 
token and processes the login (similar to how WebLogic does it with its SAML 
Identity Asserter), but wanted to see if there was a more effective approach.

Thanks,
Stu


Here are my code snippets.

Client:


@Configuration
@EnableAutoConfiguration
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(Application.class, args);
    }

    @Bean
    public HelloWorld helloService() {
        
          JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
          factory.setWsdlLocation("classpath:wsdl/hello.wsdl");        
        factory.setAddress("http://myserver/ws-server-1.0/api/hello";);      
        
factory.setServiceName(QName.valueOf("{http://service.spring.demo/}HelloWorldImplService";));
        
factory.setEndpointName(QName.valueOf("{http://service.spring.demo/}HelloWorldImplPort";));
        factory.setServiceClass(HelloWorld.class);

        Map<String, Object> props = new HashMap<String, Object>();
        props.put("ws-security.callback-handler", new 
KeystoreCallbackHandler());
       
        props.put("ws-security.signature.username", "alice");
        props.put("ws-security.signature.properties", "alice.properties");
        
        props.put("ws-security.saml-callback-handler", new 
demo.spring.service.SamlCallbackHandler());
        factory.setProperties(props);
        HelloWorld client = (HelloWorld) factory.create();
        return client;
    }
}

Client Callback (similar to systest callback):

    public void handle(Callback[] callbacks) throws IOException, 
UnsupportedCallbackException {
// snip
                callback.setIssuer("sts");
                String subjectName = "uid=sts-client,o=mock-sts.com";
                String subjectQualifier = "www.mock-sts.com";
                if (!saml2 && 
SAML2Constants.CONF_SENDER_VOUCHES.equals(confirmationMethod)) {
                    confirmationMethod = SAML1Constants.CONF_SENDER_VOUCHES;
                }
                SubjectBean subjectBean = 
                    new SubjectBean(
                        subjectName, subjectQualifier, confirmationMethod
                    );             
                callback.setSubject(subjectBean);
    
                try {
                    Crypto crypto = 
CryptoFactory.getInstance(cryptoPropertiesFile);
                    callback.setIssuerCrypto(crypto);
                    callback.setIssuerKeyName(cryptoAlias);
                    callback.setIssuerKeyPassword(cryptoPassword);
                    callback.setSignAssertion(signAssertion);
                } catch (WSSecurityException e) {
                    throw new IOException(e);
                }
            }


Service:

@WebService(endpointInterface = "demo.spring.service.HelloWorld")
public class HelloWorldImpl implements HelloWorld {

  @Resource
    WebServiceContext wsContext;
    
    public String sayHi(String text) {
        Principal pr = wsContext.getUserPrincipal();       
        String username = "";
        if (pr != null) username = pr.getName();
        System.out.println("sayHi called");
        return "Ping " + username + " - " + text;
    }
}


This always prints  “Ping 

Reply via email to