I ended up solving this one without using Apache CXF -- instead opting to go Jersey.
I did this by creating two JAXRS filters. This first filter intercepts 401 responses from the server, follows the authentication point address returned in the "WWW-Authenticate" header and performs the BASIC authentication. The original request is then replayed to the server.
The second part of this equation is another filter that handles maintaining the session cookies. Thus, when the initial request is replayed, the authentication cookie is present.
The two filters look like this:
class AuthenticationFilter implements ClientResponseFilter {
private final String username;
private final String password;
public AuthenticationFilter(String username, String password) {
this.username = username;
this.password = password;
}
@Override
public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
if (responseContext.getStatus() == Response.Status.UNAUTHORIZED.getStatusCode()) {
String header = responseContext.getHeaders().getFirst(WWW_AUTHENTICATE);
// Check if we have been given the authentication redirect go-ahead.
if (!header.startsWith("LWSSO")) {
return;
}
String authUri = header.substring(13, header.length() - 1);
Client client = ClientBuilder.newClient(requestContext.getConfiguration());
String credentials = "Basic " + Base64.getEncoder().encodeToString((username + ":" + password).getBytes());
Response response = client.target(authUri).path("authenticate").request(MediaType.TEXT_PLAIN_TYPE).header(AUTHORIZATION, credentials).get();
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
URI uri = requestContext.getUri();
MediaType mediaType = requestContext.getMediaType();
String method = requestContext.getMethod();
NewCookie cookie = response.getCookies().get("LWSSO_COOKIE_KEY");
MultivaluedMap<String, Object> headers = requestContext.getHeaders();
headers.remove(WWW_AUTHENTICATE);
Invocation.Builder builder = requestContext.getClient().target(uri).request(mediaType).headers(headers).cookie(cookie);
Invocation invocation;
if (requestContext.getEntity() != null) {
invocation = builder.build(method, Entity.entity(
requestContext.getEntity(), mediaType));
} else {
invocation = builder.build(method);
}
Response replayed = invocation.invoke();
responseContext.setStatus(replayed.getStatus());
responseContext.setStatusInfo(replayed.getStatusInfo());
if (replayed.hasEntity()) {
responseContext.setEntityStream(replayed
.readEntity(InputStream.class));
}
responseContext.getHeaders().clear();
responseContext.getHeaders()
.putAll(replayed.getStringHeaders());
}
}
}}
class SessionFilter implements ClientRequestFilter, ClientResponseFilter {
private final Map<String, NewCookie> cookies = new HashMap<String, NewCookie>();
@Override
public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
cookies.putAll(responseContext.getCookies());
}
@Override
public void filter(ClientRequestContext requestContext) throws IOException {
for(NewCookie cookie: cookies.values()) {
requestContext.getHeaders().add("Cookie", cookie);
}
}
}