whitelabel.cloud.wsclient.WebServiceAuthenticator.java Source code

Java tutorial

Introduction

Here is the source code for whitelabel.cloud.wsclient.WebServiceAuthenticator.java

Source

/**
 *
 */
/**
 *
 * Copyright (c) 2012 <copyright Aruba spa>
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
 * and associated documentation files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 *
 */
package whitelabel.cloud.wsclient;

import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Date;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Dispatch;

import org.apache.log4j.Logger;
import org.springframework.security.crypto.codec.Base64;

import whitelabel.cloud.adapter.DateFormatterExt;
import whitelabel.cloud.exception.WsAuthenticationException;

/**
 * @author luca
 *
 */
public class WebServiceAuthenticator {

    private static final Logger LOG = Logger.getLogger(WebServiceAuthenticator.class);
    private final DateFormatterExt dfe = new DateFormatterExt("yyyy-MM-dd'T'HH:mm:ss'Z'");

    private MessageDigest digest = null;
    private SecureRandom random = null;

    public void authenticateBasic(final Dispatch<SOAPMessage> dispatch, final String username,
            final String password) throws WsAuthenticationException {

        if (dispatch == null) {
            LOG.error(" SoapMessage dispatcher not defined");
            throw new WsAuthenticationException("SOAP_DISPATCHER_NOT_DEFINED");
        }
        if (username == null || password == null || username.trim().length() == 0
                || password.trim().length() == 0) {
            LOG.error("Username: " + username + " password: " + password + " - invalid parameters");
            throw new WsAuthenticationException("INVALID_PARAMETERS");
        }
        dispatch.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, username);
        dispatch.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, password);
    }

    public void authenticateInClear(final SOAPMessage request, final String username, final String password)
            throws WsAuthenticationException {

        if (request == null) {
            LOG.error(" SoapMessage request not defined");
            throw new WsAuthenticationException("SOAP_REQUEST_NOT_DEFINED");
        }
        if (username == null || password == null || username.trim().length() == 0
                || password.trim().length() == 0) {
            LOG.error("Username: " + username + " password: " + password + " - invalid parameters");
            throw new WsAuthenticationException("INVALID_PARAMETERS");
        }

        String nonceValue = generateNonceBase64(16);
        String createdValue = dfe.print(new Date());
        String userValue = username;
        String pwdValue = password;
        String pwdType = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText";

        QName securityQName = new QName(
                "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Security",
                "wsse");
        QName usernameTokenQName = new QName(
                "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
                "UsernameToken", "wsse");
        QName usernameQName = new QName(
                "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Username",
                "wsse");
        QName PasswordQName = new QName(
                "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Password",
                "wsse");
        QName PasswordTypeQName = new QName("Type");
        QName nonceQName = new QName(
                "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Nonce",
                "wsse");
        QName createdQName = new QName(
                "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "Created",
                "wsu");

        try {
            SOAPElement securitySoap = request.getSOAPHeader().addChildElement(securityQName);
            SOAPElement usernameTokenSoap = securitySoap.addChildElement(usernameTokenQName);
            SOAPElement usernameSoap = usernameTokenSoap.addChildElement(usernameQName);
            usernameSoap.addTextNode(userValue);
            SOAPElement passwordSoap = usernameTokenSoap.addChildElement(PasswordQName);
            passwordSoap.addTextNode(pwdValue);
            passwordSoap.addAttribute(PasswordTypeQName, pwdType);
            SOAPElement nonceSoap = usernameTokenSoap.addChildElement(nonceQName);
            nonceSoap.addTextNode(nonceValue);
            SOAPElement creadedSoap = usernameTokenSoap.addChildElement(createdQName);
            creadedSoap.addTextNode(createdValue);
        } catch (SOAPException se) {
            LOG.error(se);
            throw new WsAuthenticationException("SOAPHEADER_CREATION", se);
        }
    }

    public void authenticateWithDigest(final SOAPMessage request, final String username, final String password)
            throws WsAuthenticationException {

        if (request == null) {
            LOG.error(" SoapMessage request not defined");
            throw new WsAuthenticationException("SOAP_REQUEST_NOT_DEFINED");
        }
        if (username == null || password == null || username.trim().length() == 0
                || password.trim().length() == 0) {
            LOG.error("Username: " + username + " password: " + password + " - invalid parameters");
            throw new WsAuthenticationException("INVALID_PARAMETERS");
        }

        String nonceValue = generateNonceBase64(16);
        String createdValue = dfe.print(new Date());
        String userValue = username;
        String pwdValue = crypthPassword(nonceValue, createdValue, password);

        String pwdType = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest";

        QName securityQName = new QName(
                "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Security",
                "wsse");
        QName usernameTokenQName = new QName(
                "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
                "UsernameToken", "wsse");
        QName usernameQName = new QName(
                "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Username",
                "wsse");
        QName PasswordQName = new QName(
                "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Password",
                "wsse");
        QName PasswordTypeQName = new QName("Type");
        QName nonceQName = new QName(
                "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Nonce",
                "wsse");
        QName createdQName = new QName(
                "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "Created",
                "wsu");

        SOAPElement securitySoap;
        try {
            securitySoap = request.getSOAPHeader().addChildElement(securityQName);
            SOAPElement usernameTokenSoap = securitySoap.addChildElement(usernameTokenQName);
            SOAPElement usernameSoap = usernameTokenSoap.addChildElement(usernameQName);
            usernameSoap.addTextNode(userValue);
            SOAPElement passwordSoap = usernameTokenSoap.addChildElement(PasswordQName);
            passwordSoap.addTextNode(pwdValue);
            passwordSoap.addAttribute(PasswordTypeQName, pwdType);
            SOAPElement nonceSoap = usernameTokenSoap.addChildElement(nonceQName);
            nonceSoap.addTextNode(nonceValue);
            SOAPElement creadedSoap = usernameTokenSoap.addChildElement(createdQName);
            creadedSoap.addTextNode(createdValue);
        } catch (SOAPException se) {
            LOG.error(se);
            throw new WsAuthenticationException("SOAPHEADER_CREATION", se);
        }
    }

    private final String crypthPassword(String nonce, String created, String password) {
        String crypto = null;
        try {
            byte[] b1 = nonce != null ? Base64.decode(nonce.getBytes("UTF-8")) : new byte[0];
            byte[] b2 = created != null ? created.getBytes("UTF-8") : new byte[0];
            byte[] b3 = password.getBytes("UTF-8");
            byte[] b4 = new byte[b1.length + b2.length + b3.length];

            int offset = 0;
            System.arraycopy(b1, 0, b4, offset, b1.length);
            offset += b1.length;

            System.arraycopy(b2, 0, b4, offset, b2.length);
            offset += b2.length;

            System.arraycopy(b3, 0, b4, offset, b3.length);

            byte[] digestBytes = generateDigest(b4);

            crypto = new String(Base64.encode(digestBytes));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return crypto;
    }

    /**
      * Generate a (SHA1) digest of the input bytes. The MessageDigest instance that backs this
      * method is cached for efficiency.
      * @param inputBytes the bytes to digest
      * @return the digest of the input bytes
      * @throws WSSecurityException
      */
    private final byte[] generateDigest(byte[] inputBytes) {
        try {
            if (digest == null) {
                digest = MessageDigest.getInstance("SHA-1");
            }
            return digest.digest(inputBytes);
        } catch (Exception e) {
            throw new RuntimeException("Error in generating digest", e);
        }
    }

    /**
      * Generate a nonce of the given length using the SHA1PRNG algorithm.
      * The SecureRandom instance that backs this method is cached for efficiency.
      *
      * @return a nonce of the given length
      * @throws WSSecurityException
      */
    private final String generateNonceBase64(int length) {
        try {
            if (random == null) {
                random = SecureRandom.getInstance("SHA1PRNG");
                random.setSeed(System.currentTimeMillis());
            }
            byte[] temp = new byte[length];
            random.nextBytes(temp);

            //return temp;
            return new String(Base64.encode(temp));
        } catch (Exception ex) {
            throw new RuntimeException("Error in generating nonce of length " + length, ex);
        }
    }
}