8. Security Manual

8.1. Writing a Secure Web Service Client

First create a suitable payload to be sent to the echo service.

$req_payload_string =  <<<XML <ns1:echoString xmlns="http://www.wsf.org/echo/echoString"><text>Hello RM!</text></ns1:echoString>XML;

Note that in order to run security clients or services, you should engage WS-Addressing

          $reqMessage =                           new WSMessage($reqPayloadString,
                array("to" =>"http://localhost/samples/security_service.php",
                                                action" =>"http://wso2.org/wsfphp/samples/echoString"));

Then create a WSPolicy object with the security options to match your requirements.

For example, if you want to include TimeStamp and UsernameToken you can do as follows.

$policy = new WSPolicy(array("security" => array("useUsernameToken" => TRUE, "includeTimeStamp" => TRUE)));

Note: If you wish to use a policy file instead of an options array you can directly set a policy XML file.

$policy_xml = file_get_contents("policy.xml");

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

Next create a SecurityToken object with appropriate security properties.

If you want to have the UsernameToken, then the user, password and passwordType (optional) options must be set. For TimeStamp, the ttl option must be set. Hence the SecurityToken object is created as

$sec_token = new WSSecurityToken(array("user" => "bob",
             "password" => "bob12",
             "passwordType" => "Digest",
             "ttl" => 300));

Then create the client using the policy object and security token object.

$client = new WSClient(array("useWSA" => TRUE,
             "policy" => $policy,
             "securityToken" => $sec_token));

$resMessage = $client->request($reqMessage);

8.2. Writing a Secure Web Service

Make sure that the addressing action is set in WSService.

function echoFunction($inMessage) {

$returnMessage = new WSMessage($inMessage->str);

             return $returnMessage;
}

$operations = array("echoString" => "echoFunction");

$actions = array("http://wso2.org/wsfphp/samples/echoString" => "echoString");

If the client has specified the username and timestamp, these options should be set in the server side also.

$policy = new WSPolicy(array("security"=>array("useUsernameToken" => TRUE,
             "includeTimeStamp" => TRUE)));

Note: If you wish to use a policy file instead of an options array, you can directly set the policy XML file.

$policy_xml = file_get_contents("policy.xml")

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

Username and password must be provided for validation on the server side.

$sec_token = new WSSecurityToken(array("user" => "bob", "password" => "bob12", "passwordType" =>"Digest',
             ""ttl" => 100));
$svr = new WSService(array("operations" => $operations,
             "actions" => $actions,
             "policy" => $policy,
             "securityToken" => $sec_token));

$svr->reply();

8.3. Encryption and Signing

For encryption and signing, keys and certificates must be provided using the two functions:

ws_get_cert_from_file();

ws_get_key_from_file();

8.3.1. Encryption on the Client Side

The Receivers certificate (certificate used by the server side) must be set using the "receiverCertificate" option and the private key of the client must be set using the "privateKey" option with a WSSecurityToken object instance.

First load the certificates:

$rec_cert = ws_get_cert_from_file("../keys/bob_cert.cert");
$pvt_key = ws_get_key_from_file("../keys/alice_key.pem");

Then the Policy object and the SecurityToken object have to be created. When creating the Policy object, you can also specify the algorithm suite to be used.

$policy = new WSPolicy(array("security"=>array("encrypt"=>TRUE,"algorithmSuite" => "Basic256Rsa15",)));
$sec_token = new WSSecurityToken(array("privateKey" => $pvt_key,"receiverCertificate" => $rec_cert));

8.3.2. Encryption on the Server Side

Here the certificate of the client and private key of the server are provided using a WSSecurityToken object instance.

$pub_key = ws_get_cert_from_file("../keys/alice_cert.cert");
$pvt_key = ws_get_key_from_file("../keys/bob_key.pem");

Options for WSPolicy object is the same as on the client side.

$policy = new WSPolicy(array("security"=>array("encrypt" => TRUE, "algorithmSuite" => "Basic256Rsa15")));
$sec_token = new WSSecurityToken(array("privateKey" => $pvt_key, "receiverCertificate" =>$pub_key));

8.3.3. Signing on the Client Side

For signing, the certificate and the key of the client and the certificate of the server must be set.

$my_cert = ws_get_cert_from_file("../keys/alice_cert.cert");
$my_key = ws_get_key_from_file("../keys/alice_key.pem");
$rec_cert = ws_get_cert_from_file("../keys/bob_cert.cert");

Then the Policy object and the SecurityToken object can be created:

$policy = new WSPolicy(array("security"=>array("sign"=>TRUE,"algorithmSuite" => "Basic256Rsa15",)));
$sec_token = new WSSecurityToken(array("privateKey" => $my_key, "certificate" => $my_cert, "receiverCertificate" => $rec_cert));

8.3.4. Signing on the Server Side

Here the certificate and the key of the service side must be set:

$cert = ws_get_cert_from_file("../keys/bob_cert.cert");
$pvt_key = ws_get_key_from_file("../keys/bob_key.pem");

Options for the Policy object and the SecurityToken object are the same as on the client side.

$policy = new WSPolicy(array("security"=>array("sign" => TRUE,"algorithmSuite" => "Basic256Rsa15")));
$sec_token = new WSSecurityToken(array("privateKey" => $pvt_key, "certificate" => $cert));

8.3.5 Secure conversation

Secure conversation is supported using a set of callback functions and configured using the policy files. At service, you can specify operation level policies using the "opPolicies" array. In the default configuration, the establishment of the secure conversation token / security context token happens when first message is sent. By using the option "UseOwnSTS" you can configure a service to act as a security token service in addition to providing the service functionality.

It is users responsibility to implement the persisting of the security tokens ( Secure conversation token/Security Context Token ) across multiple messages. The tokens are provided in string from to the service or client using callback functions. 

Following code samples demonstrate how to configure a client.

 $policy_xml = file_get_contents("policy.xml");

$policy = new WSPolicy($policy_xml);

$security_token = new WSSecurityToken(array("user" => "Raigama", "password" => "RaigamaPW", "passwordType" => "Digest", "storeSCTCallback" => "sct_store_callback", "getSCTCallback" => "sct_get_callback", "deleteSCTCallback"=>"sct_delete_callback"));

Here, functions "sct_store_callback", "sct_get_callback", "sct_delete_callback" are callback function names.

Following code sample demonstrate how to configure a service.

$security_token = new WSSecurityToken(array("user" => "Raigama", "password" => "RaigamaPW", "passwordType" => "Digest", "storeSCTCallback" => "sct_store_callback", "getSCTCallback" => "sct_get_callback", "deleteSCTCallback"=>"sct_delete_callback"));

Again the sct_store_callback, sct_get_callback, sct_delete_callback are user implemented php functions which are registered as callbacks.

$svr = new WSService(array("operations" => $operations, "actions" => $actions, "opPolicies"=>array("echoString"=>$policy),  "useOwnSTS"=>true, "securityToken" => $security_token));

Here the service is configured to act as  a security token service in addition providing the service functionality.

8.4. Code Sample on Encryption

Client Code:

$reqPayloadString = <<<XML
<ns1:echo xmlns:ns1="http://wso2.org/wsfphp/samples"><text>Hello
World!</text></ns1:echo>
XML;

try {

    $rec_cert = ws_get_cert_from_file("../keys/bob_cert.cert");
    $pvt_key = ws_get_key_from_file("../keys/alice_key.pem");

    $reqMessage = new WSMessage($reqPayloadString,
        array("to"=>"http://localhost/samples/security/encryption/encrypt_service.php",
              "action" => "http://wso2.org/wsfphp/samples/echoString"));

    $sec_array = array("encrypt"=>TRUE, "algorithmSuite" => "Basic256Rsa15",
                       "securityTokenReference" => "IssuerSerial");

    $policy = new WSPolicy(array("security"=>$sec_array));
    $sec_token = new WSSecurityToken(array("privateKey" => $pvt_key, 
                                            "receiverCertificate" => $rec_cert));

    $client = new WSClient(array("useWSA" => TRUE, "policy" => $policy, 
                                 "securityToken" => $sec_token));

    $resMessage = $client->request($reqMessage);

    printf("Response = %s \n", $resMessage->str);

} catch (Exception $e) {

    if ($e instanceof WSFault) {
        printf("Soap Fault: %s\n", $e->Reason);
    } else {
        printf("Message = %s\n",$e->getMessage());
    }
}

Service Code:

    function echoFunction($inMessage) {
        $returnMessage = new WSMessage($inMessage->str);
        return $returnMessage;
    }

    $pub_key = ws_get_cert_from_file("../keys/alice_cert.cert");
    $pvt_key = ws_get_key_from_file("../keys/bob_key.pem");

    $operations = array("echoString" => "echoFunction");

    $sec_array = array("encrypt" => TRUE, "algorithmSuite" => "Basic256Rsa15",
                       "securityTokenReference" => "IssuerSerial");

    $actions = array("http://wso2.org/wsfphp/samples/echoString" => "echoString");

    $policy = new WSPolicy(array("security"=>$sec_array));
    $sec_token = new WSSecurityToken(array("privateKey" => $pvt_key, 
                                           "receiverCertificate" =>$pub_key));

    $svr = new WSService(array("actions" => $actions, "operations" => $operations, 
                               "policy" => $policy, "securityToken" => $sec_token)); 

    $svr->reply();