This documentation is for WSO2 Identity Server 5.0.0. View documentation for the latest release.
Securing Passwords in Password Callback Handler with Carbon Secure Vault - Identity Server 5.0.0 - WSO2 Documentation
||
Skip to end of metadata
Go to start of metadata

In WSO2 Carbon products, the password callback handler class can be used to provide passwords needed for the Rampart engine to build username tokens and create signatures when sending messages. Apache Rampart is the Axis2 module which providers WS-Security feature to Axis2 Web Services. See here for a better understanding of what the password callback handler is, how it works and how it can be used.

The following is a sample callback handler class.

public class PWCBHandler implements CallbackHandler {
    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {

        for (Callback callback : callbacks) {
            WSPasswordCallback pwcb = (WSPasswordCallback) callback;
            String id = pwcb.getIdentifer();
            int usage = pwcb.getUsage();
            if (usage == WSPasswordCallback.USERNAME_TOKEN) {
                // Logic to get the password to build the username token
                if ("admin".equals(id)) {
                    pwcb.setPassword("admin");
                }
            } else if (usage == WSPasswordCallback.SIGNATURE || usage == WSPasswordCallback.DECRYPT) {
                // Logic to get the private key password for signature or decryption
                if ("client".equals(id)) {
                    pwcb.setPassword("apache");
                }
                if ("service".equals(id)) {
                    pwcb.setPassword("apache");
                }
            }
        }
    }
}

WSO2 Carbon is shipped with a Secure Vault implementation, which is a modified version of synapse Secure Vault. It can be used to avoid the hard coding of a password in the above example and retrieve it from file in secured manner.

The following instructions describe how to configure WSO2 Secure Vault for Password Callback Handler with WSO2 Identity Server.

  1. Download the WSO2 Identity Server from here.
  2. Create a configuration file named test_conf1.xml in the <IS_HOME>/repository/conf directory and add the following into the file you created.

    <testconf>
       <module serverURL="local://services/" remote="false">
           <password>admin</password>
       </module> 
    </testconf>
  3. Add the following to the <IS_HOME>/repository/conf/security/cipher-tool.properties file.

    testconf.module.password=test_conf1.xml//testconf/module/password,true
  4. Add the following to the <IS_HOME>/repository/conf/security/cipher-text.properties file.

    testconf.module.password=[admin]
  5. Go to <IS_HOME>/bin directory and execute the "sh ciphertool.sh -Dconfigure" command. 
  6. Enter the primary key store password. Use "wso2carbon" as the password here.
  7. Then add the following configurations into the test_conf1.xml file you created in step 2. 

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <testconf xmlns:svns="http://org.wso2.securevault/configuration">
       <module remote="false" serverURL="local://services/">
           <password svns:secretAlias="testconf.module.password">password</password>
       </module>
    </testconf>

    To see the results of this, open the cipher-text.properties file again and the password is encrypted as follows.

    testconf.module.password=PFQC+qjKxmDePuiR5kSSTOx6suR48UKbDpcEEZ57TcXsHIlnP+I6E2ZXOBtZ91Fk+z3b8vWV84GB\nzn9q+ZQZ0XmdTUzNTMFMV/rpkT3OVhN9MUCjlHIORhcNMt9oWiVKaQ5tO2AmFg5IIqvG/FO51q3o\nx+L8a2sF3JH9G1m203s\=
  8. The following class is used to resolve the password.

    /*
     * Copyright (c) 2006, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package org.sample.securevault;
    
    
    import org.apache.axiom.om.OMElement;
    import org.apache.axiom.om.impl.builder.StAXOMBuilder;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.wso2.carbon.utils.CarbonUtils;
    import org.wso2.securevault.SecretResolver;
    import org.wso2.securevault.SecretResolverFactory;
    import javax.xml.namespace.QName;
    import javax.xml.stream.XMLStreamException;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    public class TestConf {
        private static final Log log = LogFactory.getLog(TestConf.class);
        private String password;
        private String serverURL;
        private String remote;
        public TestConf() {
            InputStream fileInputStream = null;
            String configPath = CarbonUtils.getCarbonHome()+ File.separator + "repository" + File.separator + "conf" +
           File.separator + "conf-test1.xml";
           File registryXML = new File(configPath);
            if (registryXML.exists()) {
                try {
                    fileInputStream = new FileInputStream(registryXML);
                    StAXOMBuilder builder = new StAXOMBuilder(fileInputStream);
                    builder.setNamespaceURIInterning(true);
                    OMElement configElement = builder.getDocumentElement();
                    //Initialize the SecretResolver providing the configuration element.
                   SecretResolver secretResolver = SecretResolverFactory.create(configElement, false);
                    OMElement module = configElement.getFirstChildWithName(new QName("module"));
                    if (module != null) {
                       //same entry used in cipher-text.properties and cipher-tool.properties.
                        String secretAlias = "testconf.module.password";
                      //Resolved the secret password.
                        if (secretResolver != null && secretResolver.isInitialized()) {
                            if (secretResolver.isTokenProtected(secretAlias)) {
                                password = secretResolver.resolve(secretAlias);
                           } else {
                               password = module.getFirstChildWithName(new QName("password")).getText();
                            }
                       }
                        serverURL = module.getAttributeValue(new QName("serverURL"));
                        remote = module.getAttributeValue(new QName("remote"));
                   }
                } catch (XMLStreamException e) {
                    log.error("Unable to parse conf-test1.xml", e);
                } catch (IOException e) {
                   log.error("Unable to read conf-test1.xml", e);
                } finally {
                    if (fileInputStream != null) {
                        try {
                            fileInputStream.close();
                        } catch (IOException e) {
                            log.error("Failed to close the FileInputStream, file : " + configPath);
                        }
                    }
               }
            }
        }
    
    
        public String getPassword() {
            return password;
        }
    
        public String getServerURL() {
            return serverURL;
        }
    
        public boolean isRemote() {
            return Boolean.valueOf(remote);
        }
    
    }

    You can checkout the complete code from here.

  9. Use maven to build the files. This is done using the following command.
    mvn clean install
  10. After building the files, open the target directory and copy the org.wso2.samples.pwcb-1.0.0.jar file to the <IS_HOME>/repository/lib directory. 
  11. Start the server. Enter the key store password once again when prompted. It is "wso2carbon".
  • No labels