WS-SecurityPolicy With PHP

WS-SecurityPolicy specification defines standards for defining security policies for your web service. WSF/PHP allows you to declare your security policies according to these standards.

You can take one of following approaches to associate policies to your web service or client.

  • PHP Array to represent your policies
  • Policy file compliant with WS-Security Policy.
  • Declaring policies inline with the WSDL.

Declaring Policies with a PHP Array

This is a WSF/PHP specific API to declare policies for a web service. You don’t need to learn WS-Security Policy to write policies with this approach. You can set whether you want to use encryption, signing or usernameToken in a PHP array and create a WSPolicy object using it.

// here is the security array to declare your policies in simple manner
$sec_array = array("encrypt" => TRUE,
 "algorithmSuite" => "Basic256Rsa15",
 "securityTokenReference" => "IssuerSerial");

// creating WSPolicy instance using the policy array
$policy = new WSPolicy(array("security"=> $sec_array));

You can use this policy object to create a service along with a WSSecurityToken which contain the user parameters like the server private key and the client certificate.

$sec_token = new WSSecurityToken(array(
 "privateKey" => $server_pvt_key,
 "receiverCertificate" => $client_pub_key));

$svr = new WSService(array("actions" => $actions,
 "operations" => $operations,
 "policy" => $policy,
 "securityToken" => $sec_token)); // here is the policy object you just created

$svr->reply();

You can invoke this service just by writing a simple web service client. There also you need to provide the policies declared in the service, so the client can build his request to validate with server policies. You will be using a similar WSPolicy object to set these policies at the client side too, as show in the below code segment.

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

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

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

Declaring Policies with a Policy File

You can set your policies in the server or client side using a policy file compliant with WS-Security Policy specification. You have to take this approach if your policy requirements are too complicated, like you want to sign only some parts of the message or you want to encrypt some soap headers.

Similar to the above method, here too you will use the WSPolicy object to set your policies. But unlike the above where you give the policies as a PHP array , here you can just give the policy file as an argument to the WSPolicy constructor.

// creating the WSPolicy instance from a policy file
$policy_xml = file_get_contents("policy.xml");
$policy = new WSPolicy($policy_xml);

Here is an example of a complete policy file written according to the WS-Security Policy standards. And you can find a quick guide on WS-Security Policy from the article Understanding WS-Security Policy Language written by Nandana, a key leader of Apache Rampart project.

Declaring Policies inline in a WSDL

We use WSDL to describe our web services. WSDL has the information about the service endpoint, the transport protocols (e.g. http), messaging protocols (e.g. SOAP) and the message schemas and many others about the service. You can attach your policies inside a WSDL.

Here is an example of a WSDL with inline policies. The difference in this approach is you can set your policies separately for each messages or each operations or each endpoints of your service. The following segment of a WSDL shows how you refer to different policies which are declared in the early part of the WSDL.

     <wsdl:binding name="CalendarSOAP12Binding" type="ns1:CalendarPortType">
       <!-- Endpoint policies are declared here.
          these are common to all messages transferring
          through this protocols (i.e. SOAP12, http)-->
        <wsp:PolicyReference URI="#transport_binding_policy"/>
        <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
        <wsdl:operation name="login">
           <soap12:operation soapAction="urn:login" style="document"/>
           <wsdl:input>
              <!-- policy specific to the 'login' operation -->
              <wsp:PolicyReference URI="#username_token_policy"/>
              <soap12:body use="literal"/>
           </wsdl:input>
           <wsdl:output>
              <soap12:body use="literal"/>
           </wsdl:output>
         </wsdl:operation>
         <wsdl:operation name="register">
            <!-- no specific policies are set for the 'register' operation
            <soap12:operation soapAction="urn:register" style="document"/>
            <wsdl:input>
              <soap12:body use="literal"/>
            </wsdl:input>
            <wsdl:output>
               <soap12:body use="literal"/>
            </wsdl:output>
         </wsdl:operation>
           ....
       </wsdl:binding>

This is the binding section of a WSDL where we bind messaging protocol and transport protocols with a service endpoint. Here we have “login” and “register” operations. Note that we are referring to “transport_binding_policy” from the parent level of each operation elements. That means these policies are common to all the operation in that binding. And inside the “login” operation we are referring to “username_token_policy”, so in order to invoke this operation, you have to send username token headers. And “register” doesn’t require any operation specific policies allowing users to register without any prior authentications.

You can select any of the above mentioned approach to define policies of your web service or to invoke a web service that support WS-Policy. If your policy requirements are simple, it will be easy to use the array based approach. If your policy requirements are complex or you have a good understanding of WS-Policy and WS-Security Policy you can rely on the policy file based approach or defining policy inline with WSDL. And the former 2 methods will give you a nice separation of the logic code and security configurations. The selection is yours:)

This entry was posted in DataServices, php, REST, security, Tutorial/Guide, web services, WSDL, wsf/php, wso2, xml, xml schema and tagged , , , , , , . Bookmark the permalink.

14 Responses to WS-SecurityPolicy With PHP

  1. wunder_y says:

    Hi Dimuthu, I need your advice on a problem I am facing with policy files.
    I have a scenario where I want the server to be able to accept client requests which can be either be encrypted or signed or a combination of both and other such cases.

    I didn’t think it was possible with the sec_array option so I decided to use separate policy files for client and server.

    The client specifies its security option(eg. encryption) and server validates it against its policy which has a combination of the policy assertions using “all” and “exactlyone” tags. However it does not seem to work.

    Can you help me out and tell me where do u think im going wrong ?

    Thanks and regards !

  2. dimuthu says:

    Hi,
    Did you check the sample policies come with wsf/php pack. It has a sample for the scenario you want.

    Thanks
    Dimuthu

  3. wunder_y says:

    Thanks for your response Dimuthu. I did check the samples but all of them enable only one option.I want the server policy to be generic ie.
    to be able to accept any combination..like just timestamp , or signing or signing and encryption.If there is such a policy file can you give me the link.Thanks so much. Appreciate it !

  4. wunder_y says:

    Hi Dimuthu, for the client i used a policy file for encryption and for the server i used the policy file from the complete example.It does not
    work ! how can i make this happen ?

  5. dimuthu says:

    Can you run the sample itself?
    If so, it is a problem in your code. First try running the sample and check

  6. wunder_y says:

    sample runs fine !!!

  7. dimuthu says:

    Are you using WSF/PHP for both sides or one side .NET or Java and only the other side is PHP?

  8. wunder_y says:

    Using wsf/php on both sides. Does ws02 required normalized policy files ?

  9. dimuthu says:

    Hey,
    No, AFAIK you don’t need to normalize the policy file, neethi (policy engine inside wsf/php) will do it for you.
    Anyway if possible try normalize it yourself and try.

    Thanks
    Dimuthu

  10. wunder_y says:

    Hi Dimuthu, I tried a no. of options but with no luck..! Is there
    anyway that I can make the server give a generic policy ?

  11. dimuthu says:

    Hey,
    If you have a client side policy saying to encrypt body then the server side policy should have a compliant policy to accept the messages with encrypted. If you put the policy file in the complete sample, it expect to have all encryption, timestamp, signature, username token from the client side.

    What you can do is use ExactlyOne construct if you expect one among several policy assertion. Please go through http://wso2.org/library/3132#policyConstruct.

  12. Javier Lizarazo says:

    I have a wsdl which I create a service in which you invoke the php with a certificate and do not bring me anything, I think also a client invoking a webservice. net but I did not repond asmx.wsdl against the calling of the webservice wsdl is declared well and wsf_php.cliente.log log in I get the following:

    [error] ..\..\src\omxmlsec\error.c(94) OXS ERROR [..\..\src\omxmlsec\axiom.c:301 in oxs_axiom_get_first_child_node_by_name] invalid data , Cannot find child ReferenceList of 2009-12-14T15:04:32.588Z2009-12-14T15:09:32.588Z
    [error] ..\..\src\omxmlsec\error.c(94) OXS ERROR [..\..\src\omxmlsec\axiom.c:301 in oxs_axiom_get_first_child_node_by_name] invalid data , Cannot find child Signature of 2009-12-14T15:04:32.588Z2009-12-14T15:09:32.588Z
    [error] ..\..\src\core\transport\http\sender\http_sender.c(1419) Error occurred in transport [error] ..\..\src\core\engine\engine.c(179) Transport sender invoke failed [error] wsf_client.c(1649) [WSF/PHP] Response Payload NULL( Error number and code) => : 74 :: Error occurred in transport [info] [rampart][rampart_mod] rampart_mod shutdown [info] [rahas] Rahas module shutdown

  13. dimuthu says:

    Hi,
    Looks like some elements missing in your payload (probably elements you have declared to sign or encrypt may have been missing in your payload). Can you please double check that.

    Thanks,
    Dimuthu

Leave a Reply

Your email address will not be published. Required fields are marked *