Configure https with WS-Security

Friday, May 21, 2010

Using WS-Security Username Token alone with Transport level security, HTTPS, is quite common. By default, Username token is used with WS-Security Signature. Lets look at how to configure WS-Security Username Token with WSF/PHP.

Since, by default, WSF/PHP tries to sign the username token credentials, you would need to specify client certificate and the private key for configuring Username Token.

e.g

$security_options = array("useUsernameToken" => TRUE );

$policy = new WSPolicy(array("security" => $security_options));

$security_token = new WSSecurityToken(array("user" => "Raigama",
                                            "password" => "RaigamaPW",
                                            "passwordType" => "Digest",
                                            "privateKey" => $my_key,
                                              "certificate" => $my_cert));

I have copied a code snippet from the username token sample. As you can see, we are only configuring username token by using the option useUsernameToken in the policy configuration. However, for the WSSecurityToken configuration, I have passed both the “privateKey” option and “certificate” option. The private key refer to the client’s private key and certificate refer to client’s certificate which contains the public key of the client.  This is because, by default, UsernameToken uses signature to enhance security of username token.

Often you would need to use https transport and plaintext username password instead of a signed username token.  You can easily enable this option by specifying a policy file and an empty transportBinding element within it as follows.

<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
    xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
    <wsp:ExactlyOne>
        <wsp:All>
            <sp:TransportBinding>
                <wsp:Policy>
                </wsp:Policy>
            </sp:TransportBinding>
            <sp:SignedSupportingTokens>
                <wsp:Policy>
                    <sp:UsernameToken
                        sp:IncludeToken="
http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
                        <wsp:Policy>
                            <sp:WssUsernameToken10 />
                        </wsp:Policy>
                    </sp:UsernameToken>
                </wsp:Policy>
            </sp:SignedSupportingTokens>
        </wsp:All>
    </wsp:ExactlyOne>
</wsp:Policy>

Now create the WSPolicy object by using the policy file.

$policy = new WSPolicy($policy_string);

In the WSClient options change “to” endpoint from “http” to “https” and specify the “CACert” option.

How to configure https for Apache2.2 and consume PHP web services over https

Step 1.

Create a Certificate Authority, CA.

openssl genrsa -des3 -out ca.key 4096
openssl req -new -x509 -days 365 -key ca.key -out ca.crt

Now we have a certificate authority certificate to sign the certificate for the server.

Step 2.

Generate a key for the server.

openssl genrsa -des3 -out server.key 4096

Generate a certificate signing request

openssl req -new -key server.key -out server.csr

Optional step : remove the passphrase from the key

Rename server.key to server.key.bac.

openssl rsa -in server.key.bac -out server.key

Step3.

Sign the generated key with certificate authority

openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt

Now we have the necessary keys and certificates to configure Apache2.2 server to enable https

Step4.

copy the generated keys, certificates to a directory named keys under the conf directory.

Uncomment ssl module and ssl configuration file in httpd.conf.

LoadModule ssl_module modules/mod_ssl.so

Include conf/extra/httpd-ssl.conf

Step 5.

configure https in httpd-ssl.conf file located in conf/extra directory. Use the default settings and specify the following Files to match your local settings.

SLCertificateFile "F:/Apache2.2/conf/keys/server.crt"

SSLCertificateKeyFile "F:/Apache2.2/conf/keys/server.key"

SSLCACertificateFile "F:/Apache2.2/conf/keys/ca.crt"

#SSLVerifyClient require

SSLVerifyDepth 1

SSLVerifyClient and SSLVerifyDepth options would only be required, if you want the client to authenticate to the server using a certificate and a passphrase.

Now you have successfully configured https for your server.

When connecting to the server, you can obtain the servers certificate by using openssl.

openssl s_client –connect localhost:443 > scert.pem

Now open the scert.pem and remove the unnecessary. Only the content within the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- needed for the certificate. You certificate would look like

-----BEGIN CERTIFICATE-----

-----END CRETIFICATE-----

Step 6.

Now we can connect to a service deployed in Apache server using https and consume it.

$client = new WSClient(array(“to”=>”https://localhost/webservices/service1.php”,

                                                “CACert”=>”cert.pem”));

$response = $client->request($input);

Much more detailed discussion on implementing https alone with Axis2/C is available here.