mickey mouse
mickey mouse

Reputation: 249

Web service soap header authentication

I have a web service, i want to authenticate the user from the soap header. That is, i want to check a token id (random number) in soap header and validate it against a value in my database and if the number matches i allow the request to go through otherwise i dont want to allow execution of my web method.

Is there any clean way of doing it using SOAP headers?

Thanks,

Mrinal Jaiswal

Upvotes: 3

Views: 52065

Answers (2)

dereck
dereck

Reputation: 529

I created a web service using JDK API, and do a simple authentication by soap header. This simple project provide two services:

  • login
  • get message from server

Client posts username and password in the soap body to server, if login successfully, the server will return a token in the soap header. Clients calls getMessage service by including this token in the soap header, server check the token, if it is a logged in user, then return a success message, otherwise return a failed message.

The following is the code:

package com.aug.ws;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.WebParam.Mode;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
import javax.xml.ws.Holder;

//Service Endpoint Interface
@WebService
@SOAPBinding(style = Style.RPC)
public interface HelloWorld {

    @WebMethod
    void login(String userName, String password, @WebParam(header = true, mode = Mode.OUT, name = "token") Holder<String> token);

    String getMessage(String message);
}


package com.aug.ws;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebParam.Mode;
import javax.jws.WebService;
import javax.xml.namespace.QName;
import javax.xml.ws.Holder;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;

import com.sun.xml.internal.ws.api.message.Header;
import com.sun.xml.internal.ws.api.message.HeaderList;
import com.sun.xml.internal.ws.developer.JAXWSProperties;

@WebService(endpointInterface = "com.aug.ws.HelloWorld")
public class HelloWorldImpl implements HelloWorld {

    private Map<String, String> authorizedUsers = new HashMap<String, String>();

    @Resource
    WebServiceContext wsctx;

    @Override
    @WebMethod
    public void login(String userName, String password, @WebParam(header = true, mode = Mode.OUT, name = "token") Holder<String> token) {
        if (("user1".equals(userName) && "pwd1".equals(password)) || ("user2".equals(userName) && "pwd2".equals(password))) {
            String tokenValue = "authorizeduser1234" + userName;
            token.value = tokenValue;
            authorizedUsers.put(tokenValue, userName);

            System.out.println("---------------- token: " + tokenValue);
        }
    }

    @Override
    @WebMethod
    public String getMessage(String message) {
        if (isLoggedInUser()) {
            return "JAX-WS message: " + message;
        }
    return "Invalid access!";
    }

    /**
     * Check token from SOAP Header
     * @return
     */
    private boolean isLoggedInUser() {
        System.out.println("wsctx: " + wsctx);

        MessageContext mctx = wsctx.getMessageContext();
        HeaderList headerList = (HeaderList)     mctx.get(JAXWSProperties.INBOUND_HEADER_LIST_PROPERTY);

        String nameSpace = "http://ws.aug.com/";
        QName token = new QName(nameSpace, "token");

        try {
            Header tokenHeader = headerList.get(token, true);
            if (tokenHeader != null) {
                String user = authorizedUsers.get(tokenHeader.getStringContent());
                if (user != null) {
                    System.out.println(user + " has logged in.");
                    return true;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return false;
    }
}


package com.aug.endpoint;
import javax.xml.ws.Endpoint;

import com.aug.ws.HelloWorldImpl;

public class HelloWorldPublisher {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Endpoint.publish("http://localhost:9000/ws/hello", new HelloWorldImpl());

        System.out.println("\nWeb service published @ http://localhost:9000/ws/hello");
        System.out.println("You may call the web service now");
    }

}


package com.aug.client;

import java.net.MalformedURLException;
import java.net.URL;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;

import com.aug.ws.HelloWorld;
import com.sun.xml.internal.ws.api.message.HeaderList;
import com.sun.xml.internal.ws.api.message.Headers;
import com.sun.xml.internal.ws.developer.JAXWSProperties;
import com.sun.xml.internal.ws.developer.WSBindingProvider;

public class HelloWorldClient {

    private static final String WS_URL = "http://localhost:9000/ws/hello?wsdl";
    private static final String NAME_SPACE = "http://ws.aug.com/";

    public static String login() throws Exception {

        URL url = new URL(WS_URL);
        QName qname = new QName(NAME_SPACE, "HelloWorldImplService");

        Service service = Service.create(url, qname);
        HelloWorld hello = service.getPort(HelloWorld.class);

        hello.login("user1", "pwd1", null);

        WSBindingProvider bp = (WSBindingProvider) hello;
        HeaderList headerList = (HeaderList)     bp.getResponseContext().get(JAXWSProperties.INBOUND_HEADER_LIST_PROPERTY);
        bp.close();

        return headerList.get(new QName(NAME_SPACE, "token"), true).getStringContent();
    }

    public static void getMessage() throws Exception  {
        String token = login();
        System.out.println("token: " + token);

        URL url = new URL(WS_URL);
        QName qname = new QName(NAME_SPACE, "HelloWorldImplService");

        Service service = Service.create(url, qname);
        HelloWorld hello = service.getPort(HelloWorld.class);
        WSBindingProvider bp = (WSBindingProvider) hello;

        bp.setOutboundHeaders(
                Headers.create(new QName(NAME_SPACE, "token"), token)
        );

        System.out.println(hello.getMessage("hello world"));

        bp.close();
    }

    public static void main(String[] args) throws Exception {
        getMessage();
    }

}

Upvotes: 1

Justin Garrick
Justin Garrick

Reputation: 14947

Have you looked into WS-Security? Assuming you're not already using it for something else, you could carry your token in the Username element, etc.

<?xml version="1.0"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1">
      <wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="UsernameToken-1">
        <wsse:Username>yourusername</wsse:Username>
        <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">yourpassword</wsse:Password>
      </wsse:UsernameToken>
    </wsse:Security>
  </soapenv:Header>
  <soapenv:Body>
    <yourbodygoeshere>
  </soapenv:Body>
</soapenv:Envelope>

Upvotes: 6

Related Questions