Skip Headers
Oracle® Application Server Web Services Security Guide
10g Release 3 (10.1.3)
B15979-01
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
Next
 

4 Building Secure Web Services

This chapter provides the generalized steps for assembling a secure Web service. Oracle Application Server Web Services provides the WebServicesAssembler tool which allows you to assemble the service top down (from a WSDL) or bottom up (from Java classes, EJBs, or database resources). The tool can assemble your service either from Ant tasks in a build script or by entering commands on the command line. For a detailed description of using the WebServicesAssembler tool to build Web services, see the Oracle Application Server Web Services Developer's Guide.


Note:

The Oracle JDeveloper IDE and the Application Server Control tools can aid your development of secure Web services. You can use the Oracle JDeveloper IDE to build, configure, deploy, and test a secure Web service. You can also use Application Server Control tool to deploy, manage, and monitor it. For more information on using these tools to build and deploy Web services, see the topics Developing with Web Services in the JDeveloper on-line help and Web Services Page in the Application Server Control on-line help.

Assembling a Secure Web Service

In OracleAS Web Services Security, the security policies for a Web service are specified in XML configuration files. Some examples of the security policies they can describe include username token authentication and XML signature and encryption of the SOAP message body.

The WebServicesAssembler tool adds the policies declared in the configuration files to the Web service at assembly time. The policies can be assembled into the service by either the bottom up or top down approach. You must provide one configuration file for the server and a corresponding file for the client.

The following sections describe how to assemble security into a Web service.

These sections describe how to create the files for the server and the client. They also describe how to specify their content to implement username authentication and the XML signature and encryption security policies.

Assembling Security into a Web Service Top Down

The following steps provide a general outline of how to add a security configuration to a Web service application that is being assembled top down (from an existing WSDL). To perform this assembly, the WebServicesAssembler tool provides the topDownAssemble command. Only the steps that concern adding security are described in detail. If you need more information on an individual step, see "Assembling a Web Service from a WSDL" in the Oracle Application Server Web Services Developer's Guide.

  1. Generate the Service Endpoint Interface using WebServicesAssembler.

    Provide a WSDL from which the Web service will be generated as input to the WebServicesAssembler genInterface command.

  2. Compile the generated interfaces and type classes from Step 1 using the Java compiler.

  3. Implement the Java Service Endpoint for the Web service you want to provide.

    The Java Service Endpoint must have a method signature that matches every method in the generated Java interface in Step 1.

  4. Compile the Java Service Endpoint.

  5. Create a server-side security configuration file.

    The WebServicesAssembler tool uses this file to generate security information into the oracle-webservices.xml server-side deployment descriptor. "Creating a Server-Side Security Configuration File" provides instructions on how to create this file.

  6. (Optional) Create a keystore.

    If you are signing or encrypting data, or verifying signatures or decrypting data, you must have a keystore to store trusted certificates and public and private keys. See "Creating a Keystore" for more information on creating a Oracle Wallet or JKS keystore.

  7. (Optional) Bundle the keystore.

    If your server-side security configuration contains a <decrypt>, <verify-signature>, <verify-x509-token>, or <verify-saml-token> in the inbound policy, or if it contains an <encrypt>, <x509-token>, <saml-token>, or <signature> element in the outbound policy, then you must either bundle a keystore with your application or specify a global-level keystore.

    To bundle a keystore with your application, follow these steps:

    1. Create an ear/META-INF directory in the directory where the service is generated (that is, the directory specified as the target of the WebServicesAssembler topDownAssemble command's output argument).

    2. Copy the keystore into the ear/META-INF directory.

  8. Assemble the service.

    Assemble the Web service using WebServicesAssembler topDownAssemble command. This is where you generate the security configuration into the Web service. Note that the path to the serverConfig.xml file, which contains the security configuration, is specified with the ddFileName argument.

    java -jar wsa.jar -topDownAssemble
                      -wsdl SecureService.wsdl
                      -unwrapParameters false
                      -className oracle.demo.security.SecureServiceImpl
                      -input build/classes/service
                      -output build
                      -ear dist/secure_service.ear
                      -packageName oracle.demo.security
                      -fetchWsdlImports true
                      -ddFileName serverConfig.xml
                      -classpath ./build/classes/client/ :
                          $OC4J_HOME/jlib/jaxen.jar : 
                          $OC4J_HOME/jlib/osdt_wss.jar :
                          $OC4J_HOME/jlib/osdt_cert.jar :
                          $OC4J_HOME/jlib/osdt_xmlsec.jar :
                          $OC4J_HOME/jlib/osdt_core.jar :
                          $OC4J_HOME/jlib/osdt_saml.jar :
                          $OC4J_HOME/jlib/oraclepki.jar :
                          $OC4J_HOME/j2ee/home/jazn.jar :
                          $OC4J_HOME/j2ee/home/jazncore.jar :
                          $OC4J_HOME/j2ee/home/jaznplugin.jar
    
    

    Ant task:

    <oracle:topDownAssemble appName="secure_service"
             wsdl="./wsdl/SecureService.wsdl"
             unwrapParameters="false"
             input="build/classes/service "
             output="build"
             ear="dist/secure_service.ear"
             packageName="oracle.demo.security"
             fetchWsdlImports="true"
             ddFileName=serverConfig.xml>
             <oracle:portType
                className="oracle.demo.topdowndoclit.service.DocLitLoggerImpl"
             </oracle:portType>
             <oracle:classpath>
                 <pathelement location="build/classes/client/ /> 
                 <pathelement location="$OC4J_HOME/jlib/jaxen.jar />  
                 <pathelement location="$OC4J_HOME/jlib/osdt_wss.jar /> 
                 <pathelement location="$OC4J_HOME/jlib/osdt_cert.jar /> 
                 <pathelement location="$OC4J_HOME/jlib/osdt_xmlsec.jar /> 
                 <pathelement location="$OC4J_HOME/jlib/osdt_core.jar /> 
                 <pathelement location="$OC4J_HOME/jlib/osdt_saml.jar /> 
                 <pathelement location="$OC4J_HOME/jlib/oraclepki.jar /> 
                 <pathelement location="$OC4J_HOME/j2ee/home/jazn.jar /> 
                 <pathelement location="$OC4J_HOME/j2ee/home/jazncore.jar /> 
                 <pathelement location="$OC4J_HOME/j2ee/home/jaznplugin.jar /> 
           </oracle:classpath>
     </oracle:topDownAssemble>
    
    

    At a minimum, specify the name of the WSDL, the class name that implements the Service (generated in Step 3), and the name of the output directory. The WebServicesAssembler tool outputs an EAR file, and a WAR file within the EAR. The WAR file contains the service artifacts, the implementation classes, the Web deployment descriptor (web.xml) and the JAX-RPC deployment descriptor (webservices.xml) and oracle-webservices.xml with the security configuration.


    Note:

    If you want to authenticate the user based on the username token, then a user entry must exist with the username and password sent by client. For example, a username and password can be SCOTT and TIGER. For information on creating a file-based repository of user entries, see the Oracle Containers for J2EE Security Guide.

  9. Deploy and bind the service into a running instance of OC4J.

    You can deploy the service by using Application Server Control or by using admin_client.jar on the command line. For more information on deployment, see Deploying an Application in the Application Server Control on-line help and the Oracle Containers for J2EE Deployment Guide.

  10. Configure a security provider on the server-side to authenticate user data sent by the client.

    For more information on configuring security providers, see the Oracle Containers for J2EE Security Guide.

  11. (Optional) Check that deployment succeeded. OracleAS Web Services provides a Web Service Home Page for each deployed Web service.

    For more information on the Web Service Home Page, see the Oracle Application Server Web Services Developer's Guide.

  12. Create the client security configuration file.

    Create a client configuration file that specifies the security that will be applied to your Web service client. In this example, the file is called clientConfig.xml. The WebServicesAssembler tool uses this file to generate the client-side deployment descriptor <generated_name>_Stub.xml. "Creating a Client-Side Security Configuration File" provides instructions on how to create the client configuration file.

  13. Generate the secure client code.

    For the J2SE environment, generate stubs (client proxies) for a J2SE Web service client by running the WebServicesAssembler tool with the genProxy command.

    For information on assembling a J2EE client, see "Assembling a J2EE Client" in the Oracle Application Server Web Services Developer's Guide.

    For example, the following command generates client proxies (stubs) that can be used for a J2SE client. Note that the ddFileName argument specifies the client configuration file.

    java -jar wsa.jar -genProxy
    -wsdl http://localhost:8888/webservice/webservice?WSDL
    -unwrapParameters false
    -output build/src/client
    -packageName oracle.demo.security.stubs
    -ddFileName clientConfig.xml 
    
    

    Ant task:

    <oracle:genProxy
    wsdl="http://localhost:8888/webservice/webservice?WSDL"
    unwrapParameters="false"
    output="build/src/client"
    packageName="oracle.demo.security.stubs"
    ddFileName="clientConfig.xml"
    />
    
    

    At a minimum, specify the name of the WSDL, the name of the output directory and the name of the client configuration file. The WebServicesAssembler tool generates a <generated_name>_Stub.xml. A client application uses the stub to invoke operations on a remote service.

  14. Compile and run the client.

Assembling Security into a Web Service Bottom Up

The following steps provide a general outline of how to add a security configuration to a Web Service application that is being assembled bottom up. The WebServicesAssembler tool provides several specialized commands based on whether you are assembling the services from Java classes, EJBs, JMS destinations, or database resources. These commands are summarized in "Ant Tasks and WebServicesAssembler".

In the following example, a Web service is assembled from Java classes. To perform this assembly, the WebServicesAssembler tool provides the assemble command. Only the steps that concern adding security are described in detail. If you need more information on an individual step, see "Assembling a Web Service with Java Classes" in the Oracle Application Server Web Services Developer's Guide.

  1. Provide the compiled Java class that you want to expose as a Web service and its compiled interface.

  2. Create the Web service security configuration file.

    In this example, the file is called serverConfig.xml. The WebServicesAssembler tool uses this file to generate security information into the oracle-webservices.xml server-side deployment descriptor. "Creating a Server-Side Security Configuration File" provides instructions on how to create this file.

  3. (Optional) Create a keystore.

    If you are signing or encrypting data, or verifying signatures or decrypting data, you must have a keystore to store trusted certificates and public and private keys. See "Creating a Keystore" for more information on creating a Oracle Wallet or JKS keystore.

  4. (Optional) Bundle the keystore.

    If your server-side security configuration contains a <decrypt>, <verify-signature>, <verify-x509-token>, or <verify-saml-token> in the inbound policy, or if it contains an <encrypt>, <x509-token>, <saml-token>, or <signature> element in the outbound policy, then you must either bundle a keystore with your application or specify a global-level keystore.

    To bundle a keystore with your application, follow these steps:

    1. Create an ear/META-INF directory in the directory where the service is generated (that is, the directory specified as the target of the WebServicesAssembler output argument).

    2. Copy the keystore into the ear/META-INF directory.

  5. Assemble the secure Web service.

    Assemble the Web service by running the WebServicesAssembler tool with the appropriate *Assemble command for the Web service you are creating. Note that the path to the serverConfig.xml server configuration file is specified with the ddFileName argument.

    Note that this example assumes that the command is run on the UNIX operating system. Directory paths use the forward slash (/) and the classpath argument uses a colon (:) to separate individual classpath elements. If you are using the Windows operating system, use a back slash (\) in directory paths and separate individual classpath elements with a semicolon (;).

    java -jar wsa.jar -assemble
              -appName securehello
              -serviceName SecureHelloService
              -interfaceName oracle.demo.hello.HelloInterface
              -className oracle.demo.hello.HelloImpl
              -input ./build/classes/client
              -output build
              -ear dist/securehello.ear
              -uri SecureHelloService
              -ddFileName serverConfig.xml 
              -classpath ./build/classes/client/ :
                          $OC4J_HOME/jlib/jaxen.jar : 
                          $OC4J_HOME/jlib/osdt_wss.jar :
                          $OC4J_HOME/jlib/osdt_cert.jar :
                          $OC4J_HOME/jlib/osdt_xmlsec.jar :
                          $OC4J_HOME/jlib/osdt_core.jar :
                          $OC4J_HOME/jlib/osdt_saml.jar :
                          $OC4J_HOME/jlib/oraclepki.jar :
                          $OC4J_HOME/j2ee/home/jazn.jar :
                          $OC4J_HOME/j2ee/home/jazncore.jar :
                          $OC4J_HOME/j2ee/home/jaznplugin.jar
    
    

    Ant task:

    <oracle:assemble appName="securehello"
            serviceName'"SecureHelloService"
            input="./build/classes/client"
            output="build"
            ear="dist/securehello.ear"
            >
             <oracle:porttype
               interfaceName="oracle.demo.hello.HelloInterface"
               className="oracle.demo.hello.HelloImpl"
               <oracle:port uri="SecureHelloService" />
             </oracle:porttype>
             <oracle:classpath>
                 <pathelement location="build/classes/client/ /> 
                 <pathelement location="$OC4J_HOME/jlib/jaxen.jar />  
                 <pathelement location="$OC4J_HOME/jlib/osdt_wss.jar /> 
                 <pathelement location="$OC4J_HOME/jlib/osdt_cert.jar /> 
                 <pathelement location="$OC4J_HOME/jlib/osdt_xmlsec.jar /> 
                 <pathelement location="$OC4J_HOME/jlib/osdt_core.jar /> 
                 <pathelement location="$OC4J_HOME/jlib/osdt_saml.jar /> 
                 <pathelement location="$OC4J_HOME/jlib/oraclepki.jar /> 
                 <pathelement location="$OC4J_HOME/j2ee/home/jazn.jar /> 
                 <pathelement location="$OC4J_HOME/j2ee/home/jazncore.jar /> 
                 <pathelement location="$OC4J_HOME/j2ee/home/jaznplugin.jar /> 
             </oracle:classpath>
    </oracle:assemble>
    
    

    The output of this command is an EAR file that contains the contents of a WAR file that can be deployed to an OC4J instance. The build directory specified by the output argument contains separate directories for the EAR file and the Java classes. The dist directory contains the J2EE Web services-compliant application EAR file, securehello.ear.


    Note:

    If you want to authenticate the user based on the username token, then a user entry must exist with the username and password sent by client. For example, a username and password can be SCOTT and TIGER. See "Configuring File Based Providers" in the Oracle Containers for J2EE Security Guide for information on adding user entries to the server.

  6. Deploy and bind the service.

    You can deploy the service by using Application Server Control or by using admin_client.jar on the command line. For more information on deployment, see Deploying an Application in the Application Server Control on-line help and the Oracle Containers for J2EE Deployment Guide.

  7. Configure a security provider on the server-side to authenticate user data sent by the client.

    See the Oracle Containers for J2EE Security Guide for more information on security provider configurations.

  8. (Optional) Check that deployment succeeded. OracleAS Web Services provides a Web Service Home Page for each deployed Web service.

    For more information on the Web Services Home Page, see "Testing Web Service Deployment" in the Oracle Application Server Web Services Developer's Guide.

  9. Create a client security configuration.

    Create a client configuration file that specifies the security that will be applied to your web service client. In this example, the file is called clientConfig.xml. The WebServicesAssembler tool uses this file to generate the client-side deployment descriptor <generated_name>_Stub.xml. "Creating a Client-Side Security Configuration File" provides instructions on how to create the client configuration file.

  10. Assemble secure client code.

    For the J2SE environment, generate stubs (client proxies) for a J2SE Web service client by running the WebServicesAssembler tool with the genProxy command.

    For information on assembling a J2EE client, see "Assembling a J2EE Client" in the Oracle Application Server Web Services Developer's Guide.

    For example, the following command generates client proxies (stubs) that can be used for a J2SE client. Note that the ddFileName argument specifies the client configuration file.

    java -jar wsa.jar -genProxy
    -wsdl http://localhost:8888/webservice/webservice?WSDL
    -unwrapParameters false
    -output build/src/client
    -packageName oracle.demo.security.stubs
    -ddFileName clientConfig.xml 
    
    

    Ant task

    <oracle:genProxy
    wsdl="http://localhost:8888/webservice/webservice?WSDL"
    unwrapParameters="false"
    output="build/src/client"
    packageName="oracle.demo.security.stubs"
    ddFileName="clientConfig.xml"
    />
    
    

    At a minimum, specify the name of the WSDL, the name of the output directory, and the client configuration file. The WebServicesAssembler tool generates a <generated_name>_Stub.xml. A client application uses the stub to invoke operations on a remote service.

  11. Compile and run the client.

Creating a Server-Side Security Configuration File

This section describes how to create a server-side Web service security configuration file to verify a username token. In this example, the file is called serverConfig.xml. The WebServicesAssembler tool appends the data found in this file into the oracle-webservices.xml server-side deployment descriptor.


Note:

If you are using JDeveloper to secure your Web service, then the security configuration is automatically generated into the oracle-webservices.xml file.

The following general steps describe how to create the server-side Web service security configuration file.

  1. Create a file using any text editor.

    Example 4-1 provides a sample server-side configuration file named serverConfig.xml.

  2. Enter the XML elements to set the security configuration in the file.

    The following sections provide sample server-side Web service security configurations for username token and for XML signature and encryption.

  3. Save the file.

Defining a Server-Side, Port Level Security Configuration for Username Token

Example 4-1 illustrates a sample server-side Web services configuration file which enforces security on the port level. This means that the user name token will have to be verified before access is granted to any of the operations in the port. Note that line numbers have been added for reference purposes only. They should not appear in your file. "Security Elements for Inbound Messages" provides more information on the <verify-username-token> element for inbound security.

  • Line 2: This line identifies the Web service to which security will be applied. The name attribute value should match the service name in the WSDL.

  • Line 3: This line identifies the port name. It must match a valid port name in the WSDL.

  • Lines 4-10: In this example security is applied at port level. The <runtime enabled="security"> element indicates that at run time, Web services security will be enforced based on the policy defined in the <security> element. Since security is configured at port level in this example, the same security will be applied to all operations exposed by this Web service.

  • Lines 6-8: These lines configure the inbound security for the incoming request. In this example, the <verify-username-token/> element indicates that the Web service application is expecting a username token in the request header. You can also enforce the password type and whether a nonce is required. See "Security Elements for Inbound Messages" for more information on this element.

  • Lines 11-13: These lines define the operations that the Web service port exposes.

Example 4-1 Sample Server-Side Configuration File for Port-Level Username Token Verification

1. <oracle-webservices>
2.   <webservice-description name="SecureService">
3.       <port-component name="SecureServiceSoap">
4.       <runtime enabled="security"> 
5.       <security>
6.          <inbound>
7.           <verify-username-token/>
8.          </inbound>
9.       </security>
10.      </runtime>
11.      <operations>
12.        <operation name="getCatalog"/>
13.      </operations>
14.      </port-component>
15.   </webservice-description>
16. </oracle-webservices>

Defining a Server-Side, Operation-Level Security Configuration for Username Token

Example 4-2 illustrates a sample server-side Web services configuration file which enforces security on the operation level. This means that the username token will have to be verified before access is granted to the specified operation. Note that line numbers have been added for reference purposes only. They should not appear in your file. See "Security Elements for Inbound Messages". for more information on the <verify-username-token>element.

This configuration is similar to Example 4-1 with one major difference:

  • Lines 6-14: The username verification is applied only for the getCatalog operation.

Example 4-2 Sample Server-Side Configuration File for Operation Level Username Token Verification

1. <oracle-webservices>
2.   <webservice-description name="SecureService">
3.   <port-component name="SecureServiceSoap">
4.       <runtime enabled="security"/> 
5.   <operations>
6.     <operation name="getCatalog">
7.     <runtime>
8.     <security>
9.     <inbound>
10.       <verify-username-token/>
11.    </inbound>
12.    </security>
13.    </runtime>
14.  </operation>
15. </operations>
16. </port-component>
17. </webservice-description>
18. </oracle-webservices>

Defining a Server-Side, Port-Level Security Configuration to Verify XML Signature and Decryption

Since the settings are made on the port level, verification must take place before access is granted to any of the operations in the port. See "Keystore Elements" and "Signature and Encryption Key Elements" for more information on configuring keystore, encryption and signature elements. Note that line numbers have been added for reference purposes only. They should not appear in your file.

  • Lines 4 -25: These lines set the keystore, keys, and inbound policy at the port level. Chapter 3, "Administering Web Services Security" provides more information on generating keystore and keys.

  • Lines 6-8: These lines set the key-store path attribute to point to the keystore that is deployed with the application. The store-pass attribute contains the keystore password. The signature-key alias attribute is used to verify the trusted certificate. The encryption-key alias attribute is used to decrypt the message. Note that signalias/encalias must be in the testks.jks file.

  • Lines 11-18: These lines specify the message integrity policy. The server expects the body and the timestamp to be signed. The signature must have a timestamp with the created value set to the creation time. The expiry attribute specifies when the signature will expire (that is, the current time must be less than the value of the creation time plus the value of expiry). The value of the clock-skew attribute is used to adjust the system clocks, when the Web service client and the Web service are on different machines.

  • Lines 19-23: These lines specify the message confidentiality policy. The server expects the content of the message body to be encrypted.

Example 4-3 Sample Server-Side Configuration File with Keystore and Inbound Policy for Decryption and Signature Verification

1. <oracle-webservices>
2. <webservice-description name="SecureHelloService">
3. <port-component name="SecureHelloPort">
4. <runtime enabled="security">
5. <security>
6. <key-store path="META-INF/testks.jks" store-pass="keystorepwd"/>
7. <signature-key alias="signalias" key-pass="signkeypwd"/>
8. <encryption-key alias="encalias" key-pass="enckeypwd"/>
9.     </security>
10.    <inbound>
11.      <verify-signature>
12.        <tbs-elements>
13.          <tbs-element name-space="http://schemas.xmlsoap.org/soap/envelope/" local-part="Body"/>
14.          <tbs-element name-space="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" local-part="Timestamp"/>
15.        </tbs-elements>
16.          <verify-timestamp created="true" expiry="28800"/>
17.          <property name="clock-skew" value="3000" />
18.      </verify-signature>
19.      <decrypt>
20.        <tbe-elements>
21.          <tbe-element name-space="http://schemas.xmlsoap.org/soap/envelope/" local-part="Body"/>
22.        </tbe-elements>
23.      </decrypt>
24.    </inbound>
25.   </runtime>
26.   <operations>
27.     <operation name="sayHello">
28.     </operation>
29.   </operations>
30.   </port-component>
31.   </webservice-description>
32. </oracle-webservices>

Defining a Server-Side, Operation-Level Security Configuration for XML Signature and Decryption

Example 4-4 illustrates a sample server-side Web services configuration file where the global level keystore settings are used for signature verification and decryption. Note that line numbers have been added for reference purposes only. They should not appear in your file.

  • Lines 7-26: These lines indicate that security is enforced for the sayHello() operation. The server expects to receive signed and encrypted messages.

  • Lines 10-17: These lines specify the message integrity policy. The server expects the message body and the timestamp to be signed. The signature must have a timestamp with the created value set to creation time. The expiry attribute specifies when the timestamp will expire (that is, the current time must be less than the value of the creation time plus the value of expiry). The clock-skew attribute is used to adjust the system clocks, when the Web service client and the Web service are on different machines.

  • Lines 18 -22: These lines specify the message confidentiality policy. The server expects the content of the body to be encrypted.

Example 4-4 Sample Server-Side Configuration File with Operation-Level Decryption and Signature Verification

1. <oracle-webservices>
2.   <webservice-description name="SecureHelloService">
3.   <port-component name="SecureHelloPort">
4.   <runtime enabled="security"> 
5.   <operations>
6.     <operation name="sayHello">
7.     <runtime>
8.     <security>
9.     <inbound>
10.     <verify-signature>
11.      <tbs-elements>
12.        <tbs-element name-space="http://schemas.xmlsoap.org/soap/envelope/" local-part="Body"/>
13.        <tbs-element name-space="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" local-part="Timestamp"/>
14.      </tbs-elements>
15.        <verify-timestamp created="true" expiry="28800"/>
16.        <property name="clock-skew" value="3000" />
17.    </verify-signature>
18.    <decrypt>
19.      <tbe-elements>
20.        <tbe-element name-space="http://schemas.xmlsoap.org/soap/envelope/" local-part="Body"/>
21.      </tbe-elements>
22.    </decrypt>
23.    </inbound>
24.    </security>
25.    </runtime>
26.    </operation>
27.   </operations>
28.  </port-component>
29.  </webservice-description>
30. </oracle-webservices>

Creating a Client-Side Security Configuration File

This section describes how to create a client-side Web service security configuration file to generate a username token. In this example, the file is called clientConfig.xml. The WebServicesAssembler tool appends the data found in this file into the <generated_name>_Stub.xml client-side deployment descriptor.


Note:

If you are using JDeveloper to secure your Web service, then the security configuration is automatically generated into the <generated_name>_Stub.xml file.

The following general steps describe how to create the client-side Web service security configuration file.

  1. Create a file using any text editor.

    Example 4-5 provides a sample client-side configuration file named clientConfig.xml.

  2. Enter the XML elements to generate a username token security configuration in the file.

    The following sections provide examples of client-side security configuration files for username token and for signature and encryption.

  3. Save the file.

Defining a Client-Side, Port Level Security Configuration for Username Token

Example 4-5 illustrates a sample client-side Web services configuration file which enforces security on the port level. In this example, the client must send a user name and password to access any operations that the service exposes at the port level. Note that line numbers have been added for reference purposes only. They should not appear in your file. "Username Token Elements for Outbound Messages" provides more information on the <username-token> element.

  • Lines 4-10: In this example, security is applied at port level. The <runtime enabled="security"> element indicates that at run time, the client will be secured based on the policy defined in the <security> element. Since the security is configured at the port level, the same security will be applied to all operations of the Web service.

  • Lines 6-8: The <outbound> clause is where you define the outbound message policy. The <username-token> element indicates that a username token will be added to the security header with username SCOTT and password TIGER. You can also specify the password type as either PLAINTEXT (default) or DIGEST.

Example 4-5 Sample Client-Side Web Services Configuration File with Port-Level Username Token Security

1. <oracle-webservice-clients>
2.  <webservice-client>
3.   <port-info>
4.   <runtime enabled="security">
5.   <security>
6.   <outbound>
7.     <username-token name="SCOTT " password="TIGER"/>
8.   </outbound>
9.   </security>
10.   </runtime>
11.     <operations>
12.     <operation name="sayHello"/>
13.    </operations>
14. </port-info>
15. </webservice-client>
16. </oracle-webservice-clients>

Defining a Client-Side, Port-Level Security Configuration for XML Signature and Encryption

Example 4-6 illustrates a sample client-side Web services configuration file which enforces security on the port level. In this example, the configuration sets the security policy for the client side keystore, the key configuration policy, and the outbound message policy. Note that line numbers have been added for reference purposes only. They should not appear in your file.

  • Lines 4-24: These lines specify the security policy for the client side keystore, the key configuration policy, and the outbound message policy. You must generate the keystore and the signature and encryption keys. For more information on creating a keystore and adding keys, see "Using Keystores".

  • Lines 6-7: These lines specify the client side keystore path and signature key alias.

  • Lines 8-22: These lines specify the outbound message policy.

  • Lines 9-15: These lines specify the signature policy. In this example, these lines indicate that the body and timestamp must be signed.

  • Lines 16-21: Specify the encryption policy and the recipients key that will be used to encrypt the request.

Example 4-6 Sample Client-Side Web Services Configuration File with Port Level Signature and Encryption Security

1. <oracle-webservice-clients>
2.  <webservice-client>
3. <port-info>
4.   <runtime enabled="security">
5.   <security>
6.     <key-store path="etc/testks.jks" store-pass="keystorepwd"/>
7.     <signature-key alias="signalias" key-pass="signkeypwd"/>
8.       <outbound>
9.        <signature>
10.          <tbs-elements>
11.            <tbs-element name-space="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" local-part="Timestamp"/>
12.           <tbs-element name-space="http://schemas.xmlsoap.org/soap/envelope/" local-part="Body"/>
13.         </tbs-elements>
14.           <add-timestamp created="true" expiry="28800"/>
15.       </signature>
16.       <encrypt>
17.         <tbe-elements>
18.           <tbe-element name-space="http://schemas.xmlsoap.org/soap/envelope/" local-part="Body"/>
19.           </tbe-elements>
20.           <recipient-key alias="encalias"/>
21.       </encrypt>
22.      </outbound>
23.  </security>
24.  </runtime>
25.  <operations>
26.    <operation name="sayHello">
27.    </operation>
28.  </operations>
29. </port-info>
30. </port-component>
31. </webservice-description>
32. </oracle-webservices>
33. </webservice-client>
34. </oracle-webservice-clients> 

Creating Users For Authentication

The server requires username and password data to authenticate users trying to access the Web service secured with the username policy. To provide this data, you can enter information for each user in the instance level system-jazn-data.xml file. You can find this file at OC4J_HOME/j2ee/<instance_name>/config/system-jazn-data.xml. For more information on the contents of the system-jazn-data.xml file, see the Oracle Containers for J2EE Security Guide.

Adding User Entries via Application Server Control

The Application Server Control console provides screens where you can create users and passwords and add them to the server. For more information, see the topic Managing Security Provider Roles and Users in the Application Server Control on-line help.

Client JAR Files

Example 4-6 lists the client JAR files required if you are assembling security into your Web service client. "Web Service APIs and JARs" in the Oracle Application Server Web Services Developer's Guide lists the other JARs that must appear on the classpath to compile a Web service client.

Table 4-1 Client JAR Files for Security

JAR Name and Path Description

OC4J_HOME/jlib/jaxen.jar

Contains the classes that define Jaxen—a Java XPath Engine capable of evaluating XPath expressions across multiple modes (such as dom4j, JDOM, and so on).

OC4J_HOME/jlib/osdt_wss.jar

Contains Oracle Security Developer's Toolkit Web services security (WS-Security) APIs.

OC4J_HOME/jlib/osdt_cert.jar

Contains the Oracle Security Developer's Toolkit cryptography APIs.

OC4J_HOME/jlib/osdt_xmlsec.jar

Contains Oracle Security Developer's Toolkit XML signing and encryption APIs.

OC4J_HOME/jlib/osdt_core.jar

Contains the Oracle Security Developer's Toolkit (OSDT) APIs

OC4J_HOME/jlib/osdt_saml.jar

Contains Oracle Security Developer's Toolkit Security Assertion Markup Language (SAML) APIs.

OC4J_HOME/jlib/oraclepki.jar

Contains the Oracle orapki keytool utility.

OC4J_HOME/j2ee/home/jazn.jar

Contains the JAZN (Oracle JAAS provider) administration tool.

OC4J_HOME/j2ee/home/jazncore.jar

Contains the JAZN (Oracle JAAS provider) implementation.

OC4J_HOME/j2ee/home/jaznplugin.jar

Contains the JAZN (Oracle JAAS provider) custom plug-in module.


Adding Transport-Level Security to a Web Service

You can secure a Web service on the transport level by using basic, digest, or client certification (client-cert) authentication. If your Web service was assembled from a version 2.1 or 3.0 EJB, you can secure it on the transport level by making additions to the oracle-webservices.xml deployment descriptor. This section also provides information on how to write J2SE and J2EE clients to access Web services secured on the transport level.

Adding Basic Authentication

With basic authentication, the user is prompted directly for a user name and password, without going through OracleAS Single Sign-On. A login module (such as RealmLoginModule, for example) is used to generate a login dialog.

To specify basic authentication at the transport level, provide a value of BASIC for the <auth-method> subelement of <login-config> in web.xml. For example:

<web-app ...>
   ...
   <login-config>
      <auth-method>BASIC</auth-method>
      ...
   <login-config>
   ...
</web-app>

For more information on providing basic authentication, see the Oracle Containers for J2EE Security Guide.

Adding Digest Authentication

With the digest authentication mechanism, the password that a client presents to authenticate itself is encrypted through the use of an MD5 digest. This is transmitted in the request message. From a user perspective, digest authentication behaves in the same way as basic authentication.

To specify digest authentication at the transport level, provide a value of DIGEST for the <auth-method> subelement of <login-config> in web.xml. For example:

<web-app ...>
   ...
   <login-config>
      <auth-method>DIGEST</auth-method>
      ...
   <login-config>
   ...
</web-app>

For more information on providing digest authentication see the Oracle Containers for J2EE Security Guide.

Adding Client Certification Authentication

The client certification (client-cert) method authenticates the client through HTTPS. The user must possess a public key certificate.

To specify client-cert authentication at the transport level, provide a value of CLIENT-CERT for the <auth-method> subelement of <login-config> in web.xml. For example:

<web-app ...>
   ...
   <login-config>
      <auth-method>CLIENT-CERT</auth-method>
      ...
   <login-config>
   ...
</web-app>

For more information on providing client-cert authentication, see the Oracle Containers for J2EE Security Guide.

Adding Transport-Level Security for Web Services Based on EJBs

Version 2.1 and 3.0 Enterprise Java Beans (EJBs) can be exposed as a Web service. You can define transport-level security constraints Web services based on EJBs by configuring the <ejb-transport-security-constraint> and <ejb-transport-login-config> elements in the oracle-werbservices.xml deployment descriptor.

The <ejb-transport-security-constraint> element lets you specify whether the security constraints should apply to a SOAP port, a WSDL URL, or both. You can also specify a security role and a transport guarantee.

The <ejb-transport-login-config> element lets you specify whether the EJB application uses basic authentication, digest authentication, or client certificate as its authentication mechanism.

The client of a secured EJB Web service can be configured to pass a username and password to the secured service either statically, by entering configuration parameters into the proprietary deployment descriptors, such as orion-ejb-jar.xml or orion-web.xml file, or programmatically. "Accessing Web Services Secured on the Transport Level" provides more information on writing a client that can access a secured Web service.

For more information on how to use these elements and their subelements, see the oracle-webservices-10_0.xsd schema and "Packaging and Deploying Web Services" in the Oracle Application Server Web Services Developer's Guide.

Example 4-7 illustrates <ejb-transport-security-constraint> and its subelements in the oracle-webservices.xml deployment descriptor. This element associates transport-level security constraints for a version 2.1 or 3.0 EJB exposed as a Web service. The URL of the EJB exposed as a Web service is indicated by the <endpoint-address-uri> element in the port component. The sub-elements <wsdl-url> and <soap-port> are identifiers that let you choose whether the security constraints will apply to a WSDL URL or to a SOAP port. If <wsdl-url> and <soap-port> are both present or both absent in the <ejb-transport-security-constraint> element, then the security constraints will apply to both the WSDL and the SOAP port.

Example 4-7 <ejb-transport-security-constraint> Element in oracle-webservices.xml

...
   <port-component name="String">
       <endpoint-address-uri>String</endpoint-address-uri>
       <ejb-transport-security-constraint>
             <wsdl-url/>
             <soap-port/> 
             <role-name>Manager</role-name>
             <role-name>Administrator</role-name>  
             <transport-guarantee>NONE</transport-guarantee>
       </ejb-transport-security-constraint>  
      ...
   </port-component>
...

Example 4-8 illustrates <ejb-transport-login-config> and its subelements in the oracle-webservices.xml deployment descriptor. This element configures the transport-level authentication method (such as basic, digest, or client certificate) and the realm name that should be used for this EJB application. The URL of the EJB application exposed as a Web service is indicated by the <endpoint-address-uri> element in the port component.

Example 4-8 <ejb-transport-login-config> Element in oracle-webservices.xml

...
   <ejb-transport-login-config>
       <auth-method>BASIC</auth-method>
       <realm-name>sec-ejb</realm-name>
   </ejb-transport-login-config> 
...

Accessing Web Services Secured on the Transport Level

A Web service that is secured on the transport level, either by basic or digest authentication, can be accessed by a J2SE or J2EE Web service client. To access the service, the J2EE platform provides properties that can be used by a client side proxy (stub) or a dynamic invocation of the service endpoint. These properties are used to pass the user name and password to the service.

The following properties can be used by the javax.xml.rpc.Stub and javax.xml.rpc.Call interfaces.

javax.xml.rpc.security.auth.username
javax.xml.rpc.security.auth.password

For convenience, these interfaces also define constant field values for these properties.

javax.xml.rpc.Stub.USERNAME_PROPERTY
javax.xml.rpc.Stub.PASSWORD_PROPERTY
javax.xml.rpc.Call.USERNAME_PROPERTY
javax.xml.rpc.Call.PASSWORD_PROPERTY

The following sections describe how to use these field values and properties to access the secured Web service from a J2SE or J2EE Web service client.

Accessing a Secured Service from a J2SE Client

To access a Web service secured by transport level basic or digest authentication, a J2SE client can pass a username and password by using either the stub field values, Stub.USERNAME_PROPERTY and Stub.PASSWORD_PROPERTY, or helper class methods.

Example 4-9 illustrates Web service client code which uses the Stub.USERNAME_PROPERTY and Stub.PASSWORD_PROPERTY properties.

Example 4-9 Accessing a Secured Service from a J2SE Client with Stub Properties

.... 
javax.xml.rpc.Stub port = (Stub)time.getPort();
port.setProperty(Stub.USERNAME_PROPERTY, "helen");
port.setProperty(Stub.PASSWORD_PROPERTY, "password");
...

To provide programmatic access to the service, these stub properties can be replaced by the following helper class methods:

setPassword(String userName)
setUsername(String password)

For more information on helper classes in the client utility class file, see "Writing Web Service Client Applications" in the Oracle Application Server Web Services Developer's Guide.

Accessing a Secured Service from a J2EE Client

To access a Web service secured by transport level basic or digest authentication, a J2EE client can pass a username and password to the service. This information can be passed statically, by entering it in the deployment descriptor for your Web service, or programmatically.

Passing Authentication Information in a Deployment Descriptor

To pass the username and password in a deployment descriptor, you must manually edit the <service-ref-mapping> element in the orion-*.xml file for your service.

If you are accessing the service endpoint with a static client proxy add, a <stub-property> subelement to the <service-ref-mapping> element. If you are dynamically invoking the service endpoint using Dynamic Invocation Interface (DII), add a <call-property> element instead. For more information on the <call-property> and <stub-property> elements, see the Oracle Application Server Web Services Developer's Guide.

The following steps describe how to edit the <service-ref-mapping> clause and the values you must provide for the <call-property> and <stub-property> elements.

  1. Edit the <service-ref-mapping> element of the appropriate orion-*.xml deployment descriptor for your Web service.

    • If you are working with a client proxy, enter a <stub-property> subelement for the username and password, or

    • If you are dynamically invoking the service endpoint, enter a <call-property> subelement.

  2. Specify the username property javax.xml.rpc.security.auth.username and its value in the <name> and <value> subelements of the stub- or call-property element entered in Step 1.

  3. Specify the username property javax.xml.rpc.security.auth.password and its value in the <name> and <value> subelements of the stub- or call-property element entered in Step 1.

  4. When you generate your Web service client, specify the orion-*.xml deployment descriptor as input to the WebServicesAssembler genProxy command.

Example 4-10 illustrates a sample <service-ref-mapping> clause which uses <stub-property> elements to specify a username and password to access the secured Web service.

Example 4-10 Accessing a Secured Service from a Static J2EE Client Configuration

  <service-ref-mapping name="service/MyHelloServiceRef">
      ...
      <stub-property>
               <name>javax.xml.rpc.security.auth.password</name>
               <value>welcome</value>
      </stub-property>
      <stub-property>
                 <name>javax.xml.rpc.security.auth.username</name>
                 <value>helen</value>
      </stub-property>
   </service-ref-mapping 

Passing Authentication Information Programmatically

Instead of editing the orion-*.xml file, you can use the Stub.USERNAME_PROPERTY and Stub.PASSWORD_PROPERTY properties to pass these values programmatically to the service via the setProperty method.

Example 4-11 Accessing a Secured Service from a J2EE Client Programmatically

Context ic = new InitialContext();
Service service = (Service) ic.lookup("java:comp/env/service/MyHelloServiceRef");
//Service.getPort(portQName,SEI class)
HelloInterface helloPort = (HelloInterface) service.getPort(portQName,hello.HelloInterface.class);
Stub port = (Stub) helloPort;
     port.setProperty(Stub.USERNAME_PROPERTY, "helen");
     port.setProperty(Stub.PASSWORD_PROPERTY, "password");

Propagating Identities from a Web Service to an EJB

The Oracle Web Service Security implementation provides seamless integration for propagating the user's identity when a Web service invokes an EJB.

The Web service is authenticated by using message level security. Re-authentication is not required when accessing the EJB from the Web service. The same Web service user identity is propagated to the EJB. The EJB application can access the user identity by using standard EJB methods such as javax.ejb.EjbContext.getCallerPrincipal.

Further access checks can be performed by using javax.ejb.EjbContext.isCallerInRole.


Note:

The EJB application must be configured with J2EE security. Refer to "EJB Security Configuration" in the Oracle Containers for J2EE Security Guide for more information.

Ant Tasks and WebServicesAssembler

The WebServicesAssembler tool assists in assembling OracleAS Web Services. It allows you to generate the artifacts required to develop and deploy Web services, regardless of whether you are creating the service top down (from a WSDL) or bottom up from Java classes, EJBs, JMS destinations, or database resources. The WebServicesAssembler tool can also be invoked to create Web service client objects based on a WSDL.

The WebServicesAssembler tool can be invoked either on the command line or by Ant tasks. The WebServicesAssembler tool allows you flexibility in how you assemble a Web service. You can break the assembly process into a number of steps that let you more closely control how the Web service is created.

The following list provides a summary of the tasks that you can perform with the WebServicesAssembler tool. The "Using WebServicesAssembler" chapter in the Oracle Application Server Web Services Developer's Guide provides detailed information on how to use WebServicesAssembler commands to perform each task.

Getting an Authenticated User Identity in a Web Service Application

On the server, you can obtain the name of an authorized user from the username (plaintext or digest), SAML, or X.509 security tokens. This information can be used for further validation checks before the user is allowed to access additional server resources. This section describes how you can obtain a user identity with the AccessControlContext and ServiceLifeCycle APIs.

Getting an Authenticated Subject with the AccessControlContext API

You can use methods from the java.security.AccessControlContext, java.security.AccessController, and javax.security.auth.Subject classes to get the authenticated subject.


Note:

One of the purposes of getting the authenticated subject is to perform JAAS Provider authorization. "Performing JAAS Provider Authorization on a Web Service" provides a summary of how to perform this type of authorization on a Web service.

The following general steps describe how to get the authenticated subject from an AccessController object.

  1. Create an AccessControlContext object by calling the AccessController.getContext method. The getContext method takes a "snapshot" of the current calling context and returns it in an AccessControlContext object.

  2. Get the subject of the context by using the Subject.getSubject method.

For more information on the classes and methods described in this section, see the API for the java.security and javax.security.auth packages at the following Web address.

http://java.sun.com/j2se/1.4.2/docs/api/index.html

Example 4-12 illustrates using the AccessControlContext, AccessController, and Subject APIs to get the name of an authorized user.

Example 4-12 Obtaining the Name of an Authenticated User with the AccessControlContext API

java.security.AccessControlContext context =  
           java.security.AccessController.getContext();
javax.security.auth.Subject sub = javax.security.Subject.getSubject(context);

Getting an Authenticated Principal with the ServiceLifeCycle API

You can use the javax.xml.rpc.server.ServiceLifecycle and ServletEndpointContext interfaces to obtain user information from the SAML, username, or X.509 security tokens. For example, the ServletEndpointContext.getUserPrincipal method returns the name of the authenticated user; the ServletEndpointContext.isUserInRole method returns whether the user belongs to a specific role.

For more information on the ServiceLifecycle and ServletEndpointContext interfaces, see the API for the javax.xml.rpc.server package at the following Web address.

http://java.sun.com/j2ee/1.4/docs/api/index.html

To obtain user information from the Web service, follow these general steps:

  1. Implement the ServiceLifecycle interface for the Web service.

  2. In the implementation of the ServiceLifecycle.init method, cast the context parameter to ServletEndpointContext.

  3. Call methods, such as getUserPrincipal and isUserInRole, on the ServletEndpointContext context parameter to obtain user information.

Example 4-13 illustrates how to obtain the name of an authenticated user from a secure Web service. The X509Service class in the example implements the ServiceLifecycle interface. In the init method implementation, the context parameter is cast to the ServletEndpointContext interface. The getUserPrincipal method returns access to the authenticated user name, which is obtained by a call to getName.

Example 4-13 Obtaining the Name of an Authenticated User with the ServiceLifeCycle API

package test;
 
public class SecureService implements securePort, javax.xml.rpc.server.ServiceLifecycle {
 
 private javax.xml.rpc.server.ServletEndpointContext context;
 
    public void init(Object obj) throws javax.xml.rpc.ServiceException {
        context = (javax.xml.rpc.server.ServletEndpointContext)obj;
    }
 
    public String helloUser(String message) throws java.rmi.RemoteException {
        java.security.Principal principal = context.getUserPrincipal();
        if(principal == null) {
            throw new RuntimeException("Principal not found");
        }
        String userName = principal.getName();
        return "Hi "+userName+"! "+message;
    }
    public void destroy() {
        context = null;
    }
}

Performing JAAS Provider Authorization on a Web Service

OracleAS Web Services includes OracleAS JAAS Provider, a highly scalable Java Authentication and Authorization Service (JAAS) provider. OracleAS Web Services can protect resources using JAAS authorization for enforcing fine-grained access control over protected resources.

The following general steps describe how to perform JAAS authorization on a Web service.

  1. Get the authenticated subject from the security token.

    See "Getting an Authenticated Subject with the AccessControlContext API" for more information on obtaining the authenticated subject.

  2. Use the authenticated subject to issue JAAS authentication calls, such as checkPermission.

For more information on JAAS Provider authorization, see the Oracle Containers for J2EE Security Guide.

WS-Security and XML APIs

Oracle Security Developer Tools (OSDT) provide you with the cryptographic building blocks necessary for developing robust security applications ranging from basic tasks like secure messaging to more complex projects such as securely implementing a service-oriented architecture. The tools build upon the core foundations of cryptography, public key infrastructure, Web services security and federated identity management.

You can find the Reference Guide and Javadocs for OSDT at the following Web address.

http://download-east.oracle.com/docs/cd/B14099_15/idmanage.htm

Development Decisions

Chapter 5, "Secure Web Service Usage Scenarios", presents a number of use cases that describe the different ways in which you can integrate security into a Web service.