JAX-WS Basic authentication

User Rating: 5 / 5

Star activeStar activeStar activeStar activeStar active

webservicesIn the context of an HTTP transaction, BASIC access authentication is a method for a web browser or other client program to provide a user name and password when making a request.
This tutorial shows how to perform BASIC authentication using Apache CXF Interceptors and, as alternative, the JAX-WS WeServiceContext.

One advantage of the BASIC access authentication is that all web browsers support it. It is often used by Intranet private systems, where it’s not necessary a strict security policy.

How are credentials encoded with HTTP Basic authentication ?
Before transmission, the user name is appended with a colon and concatenated with the password. The resulting string is encoded with the Base64 algorithm. For example, given the user name 'Aladdin' and password 'open sesame', the string 'Aladdin:open sesame' is Base64 encoded, resulting in 'QWxhZGRpbjpvcGVuIHNlc2FtZQ=='.

Where are credentials stored ? not in the SOAP packet but in the HTTP Header.
Here is a DUMP of a SOAP request using BASIC Authentication:

POST /windcpms/ws/CfmsInterfaceService HTTP/1.1
Content-Type: text/xml; charset=UTF-8
Accept: */*
Authorization: Basic YWRtaW5BQUE6dGVzdG53aw==
SOAPAction: ""
User-Agent: Apache CXF 2.5.0
Cache-Control: no-cache
Pragma: no-cache
Connection: keep-alive
Content-Length: 368

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>. . . . .</soap:Body>

That being said, there are several ways to achieve basic authentication. If you are using Apache CXF, a very simple and effective way is adding an Interceptor which is triggered when your Web services are Invoked.
Here is a sample one:

package com.sample.ws;

import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.cxf.binding.soap.interceptor.SoapHeaderInterceptor;
import org.apache.cxf.configuration.security.AuthorizationPolicy;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.message.Exchange;
import org.apache.cxf.message.Message;
import org.apache.cxf.transport.Conduit;
import org.apache.cxf.ws.addressing.EndpointReferenceType;



public class BasicAuthAuthorizationInterceptor extends
 SoapHeaderInterceptor {   

  public void handleMessage(Message message) throws Fault {

  AuthorizationPolicy policy = message.get(AuthorizationPolicy.class);
  // If the policy is not set, the user did not specify credentials.
  // 401 is sent to the client to indicate that authentication is required.
  if (policy == null) {
    sendErrorResponse(message, HttpURLConnection.HTTP_UNAUTHORIZED);

  String username = policy.getUserName();
  String password = policy.getPassword();

  if (!checkLogin(username,password)) {
    System.out.println("handleMessage: Invalid username or password for user: " +   policy.getUserName());
  sendErrorResponse(message, HttpURLConnection.HTTP_FORBIDDEN);

  private boolean checkLogin(String username, String password) {
   if (username.equals("admin") && password.equals("admin")) {
    return true;
   return false;

  private void sendErrorResponse(Message message, int responseCode) {
   Message outMessage = getOutMessage(message);
   outMessage.put(Message.RESPONSE_CODE, responseCode);
   // Set the response headers
   Map<String, List<String>> responseHeaders =  (Map<String, List<String>>)    message.get(Message.PROTOCOL_HEADERS);
   if (responseHeaders != null) {
     responseHeaders.put("WWW-Authenticate", Arrays.asList(new String[] { "Basic realm=realm" }));
     responseHeaders.put("Content-Length", Arrays.asList(new String[] { "0" }));
   try {
   } catch (IOException e) {

  private Message getOutMessage(Message inMessage) {
   Exchange exchange = inMessage.getExchange();
   Message outMessage = exchange.getOutMessage();
   if (outMessage == null) {
    Endpoint endpoint = exchange.get(Endpoint.class);
    outMessage = endpoint.getBinding().createMessage();
     return outMessage;

  private Conduit getConduit(Message inMessage) throws IOException {
   Exchange exchange = inMessage.getExchange();
   EndpointReferenceType target = exchange.get(EndpointReferenceType.class);
   Conduit conduit = exchange.getDestination().getBackChannel(inMessage, null, target);
   return conduit;

  private void close(Message outMessage) throws IOException {
   OutputStream os = outMessage.getContent(OutputStream.class);

The above interceptor needs to be registered either with a simple annotation at Class level of your Web service:

@InInterceptors(interceptors = "com.sample.ws.BasicAuthAuthorizationInterceptor")

or using Apache CXF configuration file:

<beans xmlns="http://www.springframework.org/schema/beans"
 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
 http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
 http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

 <import resource="classpath:META-INF/cxf/cxf-all.xml" />

   <ref bean="basicAuthAuthorizationInterceptor"/>


 <bean id="basicAuthAuthorizationInterceptor"  class="com.sample.ws.BasicAuthAuthorizationInterceptor">


Another option is using the @WebServiceContext to access the Authorization parameter contained in the Header. This is a portable solution although it needs a bit more of work to decode the credentials to Base64 to plain text.



This requires Apache commons-codec libraries. You can download them here:




Authentication can be performed using a simple function:

byte[] buf = Base64.decodeBase64(userpass.getBytes());


Here’s the full code:

public class SecuredWSImpl implements SecuredWS {

 WebServiceContext wsctx;
 public void doSomething () {

 // Execute WS business logic
 private void doAuthentication() {



 MessageContext mctx = wsctx.getMessageContext();
 Map http_headers = (Map) mctx.get(MessageContext.HTTP_REQUEST_HEADERS);
  ArrayList list = (ArrayList) http_headers.get("Authorization");
  if (list == null || list.size() == 0) {
    throw new RuntimeException("Authentication failed! This WS needs BASIC Authentication!");
  String userpass = (String) list.get(0);
  userpass = userpass.substring(5);
  byte[] buf = Base64.decodeBase64(userpass.getBytes());
  String credentials = new String(buf);
  String username = null;
  String password = null;
  int p = credentials.indexOf(":");
  if (p > -1) {
   username = credentials.substring(0, p);
   password = credentials.substring(p+1);
  else {
   throw new RuntimeException("There was an error while decoding the Authentication!");
  // This should be changed to a DB / Ldap authentication check 
  if (username.equals("admin") && password.equals("admin")) { 
  System.out.println("============== Authentication OK =============");
  else {
   throw new RuntimeException("Authentication failed! Wrong username / password!");


JBoss CheatSheet for Admins