WS-Security

Stable • Since 0.14.0

Provides CXF framework’s WS-Security implementation.

Maven coordinates

Create a new project using quarkus-cxf-rt-ws-security on code.quarkus.io or add these coordinates to your existing project:

<dependency>
    <groupId>io.quarkiverse.cxf</groupId>
    <artifactId>quarkus-cxf-rt-ws-security</artifactId>
</dependency>
Check the User guide and especially its Dependency management section for more information about writing applications with CXF Extensions for Quarkus.

Supported standards

Usage

The CXF framework’s WS-Security implementation is based on WSS4J. The example below shows how to integrate with WSS4J using interceptors.

Currently, only the programmatic WSS4JInterceptors are supported. Actions like Timestamp, UsernameToken, Signature, Encryption, etc., can be applied to the interceptors by passing the appropriate configuration properties.

A SOAP Service with WS-Security

Add the WSS4JInInterceptor to in-interceptors of your web service in application.properties:

quarkus.cxf.endpoint."/rounder".in-interceptors = org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor
The sample code snippets used in this section come from the WS-Security server integration test in the source tree of CXF Extensions for Quarkus

Then you can configure your WSS4JInInterceptor using CDI like the following:

@ApplicationScoped
public class WSS4JInInterceptorProducer {

    /** Produced in CxfWssServerTestResource */
    @ConfigProperty(name = "wss.username", defaultValue = "cxf")
    String username;

    /** Produced in CxfWssServerTestResource */
    @ConfigProperty(name = "wss.password", defaultValue = "pwd")
    String password;

    @Produces
    @Unremovable
    @ApplicationScoped
    WSS4JInInterceptor wssInterceptor() {
        final CallbackHandler passwordCallback = new CallbackHandler() {
            @Override
            public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
                for (Callback callback : callbacks) {
                    if (callback instanceof WSPasswordCallback) {
                        final WSPasswordCallback pc = (WSPasswordCallback) callback;
                        if (username.equals(pc.getIdentifier())) {
                            pc.setPassword(password);
                        }
                        return;
                    }
                }
            }
        };
        final Map<String, Object> props = new HashMap<>();
        props.put(ConfigurationConstants.ACTION, "UsernameToken");
        props.put(ConfigurationConstants.PASSWORD_TYPE, "PasswordText");
        props.put(ConfigurationConstants.USER, username);
        props.put(ConfigurationConstants.PW_CALLBACK_REF, passwordCallback);
        return new WSS4JInInterceptor(props);
    }
}

A SOAP client using WS-Security

The corresponding client implementation would be slightly different: we will use WSS4JOutInterceptor and out-interceptors in application.properties:

quarkus.cxf.client."wss-client".out-interceptors=org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor
The sample code snippets used in this section come from the WS-Security client integration test in the source tree of CXF Extensions for Quarkus

Then producing the WSS4JOutInterceptor could look like the following.

@ApplicationScoped
public class WSS4JOutInterceptorProducer {

    /** Produced in CxfWssClientTestResource */
    @ConfigProperty(name = "wss.username")
    String username;

    /** Produced in CxfWssClientTestResource */
    @ConfigProperty(name = "wss.password")
    String password;

    @Produces
    @Unremovable
    @ApplicationScoped
    WSS4JOutInterceptor wssInterceptor() {
        final CallbackHandler passwordCallback = new CallbackHandler() {
            @Override
            public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
                for (Callback callback : callbacks) {
                    if (callback instanceof WSPasswordCallback) {
                        ((WSPasswordCallback) callback).setPassword(password);
                    }
                    return;
                }
            }
        };
        final Map<String, Object> props = new HashMap<>();
        props.put(ConfigurationConstants.ACTION, "UsernameToken");
        props.put(ConfigurationConstants.PASSWORD_TYPE, "PasswordText");
        props.put(ConfigurationConstants.USER, username);
        props.put(ConfigurationConstants.PW_CALLBACK_REF, passwordCallback);
        props.put(ConfigurationConstants.ADD_USERNAMETOKEN_NONCE, "true");
        props.put(ConfigurationConstants.ADD_USERNAMETOKEN_CREATED, "true");
        return new WSS4JOutInterceptor(props);
    }
}

Please refer to WS-Security and WSS4J documentation for details.

Configuration

WSS4JInInterceptor and WSS4JOutInterceptor can be associated with a SOAP services or clients using the following configuration properties: