Main Menu
Home
About Me
Blog
Articles
FAQs
Contact Me
Search
Syndicate
feed image
 
   
Home arrow Blog arrow A simple approach to web service security part 2
A simple approach to web service security part 2 PDF Print E-mail
Written by Chintan Rajyaguru   
Sunday, 17 June 2007

About the attached code

I provide no gaurantee or warantee (expressed or implied) about the code that comes with this blog entry; use it at your own risk. The attached zip file contains helloworld-ear.ear file and helloworld-client.zip file. The ear file contains ejb code in an ejb-jar file and http router code in a war file. Importing the ear file in RAD7 will automatically create necessary projects. The helloworld-client.zip file contains the client code to test the web service. You should be able to import the zip file as project interchange file in RAD7. If you have any questions, let me know.

Summary

I will be using WebSphere Application Server (WAS) v6.1 and Apache Directory Server (Apache DS) for this example. Also, to keep this article short and simple, I will not go into the details of how to create EJB, how to configure security, how to generate client etc. Instead, I have attached the code, which you can play with. If you need more details on the steps I have skipped, let me know. Here is the summary of the steps followed by more details:

  • Configure security on the server
  • Create an ejb, expose it as a web service and configure security on service endpoint interface
  • Generate http router servlet and configure http basic authentication
  • In WAS admin console, map the application roles to ldap group
  • Generate a web service client, set username and password and test

Configure security on the server

I have explained WAS and Apache DS security configuration in my blogs

Create an EJB, expose it as a web service and configure security on service endpoint interface

The bean class is available at helloworld-ear.ear\helloworld-ejb.jar\com\taraba\security\ejb\ :
package com.taraba.security.ejb;

public class HelloWorldBean implements javax.ejb.SessionBean {
   
    public String sayHello (String name){
        System.out.println ("HelloWorldBean#sayHello() was called by "                 +name);
        System.out.println ("HelloWorldBean#sayHello() user: "                         +mySessionCtx.getCallerPrincipal().getName());
        System.out.println("HelloWorldBean#sayHello() isCallerInRole: "                 +mySessionCtx.isCallerInRole("ValidUser"));
        return "Hello World " + name;
    }

    private javax.ejb.SessionContext mySessionCtx;
    // other standard ejb methods avoided for simplicity

The sayHello() method prints a log statement, prints the username of the user calling the bean and whether the user is in ValidUser role. Finally, the method returns the string "Hello World" appended with the name supplied to the method. The EJB has already been exposed as a web service. Its WSDL file is available in the supplied ear file at helloworld-ear.ear\helloworld-ejb.jar\META-INF\wsdl\HelloWorld.wsdl.

Role based security configuration can be seen in helloworld-ear.ear\META-INF\application.xml

<security-role>
        <description>
        A user that can invoke methods on Hello World EJB</description>
        <role-name>ValidUser</role-name>
</security-role>

And in helloworld-ear.ear\helloworld-ejb.jar\META-INF\ejb-jar.xml

    ...
    <security-role-ref>

        <role-name>ValidUser</role-name>
        <role-link>ValidUser</role-link>           
    </security-role-ref>   
    ...
        <assembly-descriptor>
        <security-role>
            <description>
            A user that can invoke methods on Hello World EJB</description>
            <role-name>ValidUser</role-name>
        </security-role>
        <method-permission>
            <role-name>ValidUser</role-name>
            <method>
                <ejb-name>HelloWorld</ejb-name>
                <method-intf>Remote</method-intf>
                <method-name>sayHello</method-name>
                <method-params>
                    <method-param>java.lang.String</method-param>
                </method-params>
            </method>
            <method>
                <ejb-name>HelloWorld</ejb-name>
                <method-intf>ServiceEndpoint</method-intf>
                <method-name>sayHello</method-name>
                <method-params>
                    <method-param>java.lang.String</method-param>
                </method-params>
            </method>
        </method-permission>
    </assembly-descriptor>

The security configuration indicates that the sayHello() method of the EJB can only be invoked by the users in ValidUser role. This security configuration applies to remote and service clients (see the bold parts in the xml fragment shown above). Also review the security-role-ref section. This section is required since we are calling the isCallerInRole () method. 

The security configuration described above is explained in ejb 2.x specification. Defining security configuration of sayHello() method exposed by the Service Endpoint Interface makes the method secure for web service clients. If the web service client is not in ValidUser role, as defined in the <method-permission> tag, UnauthorizedException will be thrown.

Generate http router servlet and configure HTTP BASIC authentication

The authentication configuration is configured in helloworld-ear.ear\helloworld-http-router.war\WEB-INF\web.xml

    <security-constraint>
        <display-name>ws_constraint</display-name>
        <web-resource-collection>
            <web-resource-name>ws_resource</web-resource-name>
            <url-pattern>/services/HelloWorld</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
        </web-resource-collection>
        <auth-constraint>
            <description>Valid User</description>
            <role-name>ValidUser</role-name>
        </auth-constraint>
    </security-constraint>
    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>web service basic authentication</realm-name>
    </login-config>
    <security-role>
        <description>web services user</description>
        <role-name>ValidUser</role-name>
    </security-role>
As the bold parts of the fragment above indicate, the /services/HelloWorld url is protected for ValidUser role. The users will be authenticated using BASIC authentication.

In WAS admin console, map the security roles to LDAP groups - so that the user information can be retrieved from LDAP

In configure security on the server section, I described how to create users and groups in LDAP. We will map the ValidUser role in the application to the endusers group in LDAP using WAS admin console as shown below:

Generate a web service client and set username and password

I generated a java client from the wsdl file and packaged it in a jar file helloworld-client.jar. I then wrote a com.taraba.security.ejb.client.HelloWorldClient class with a main method as shown below:

    public static void main(String[] args) {
        HelloWorldProxy proxy = new HelloWorldProxy ();
        try {
            System.out.println (proxy.sayHello("Taraba Consulting"));
        } catch (RemoteException e) {
            e.printStackTrace();
        }

    }
As shown above, the method simply instantiates the proxy, calls sayHello method on it and prints the result. Running the client as is will return a soap fault with Unauthorized error. To fix this, uncomment the following two lines in com.taraba.security.ejb.HelloWorldProxy#sayHello().
    //  ((javax.xml.rpc.Stub)__helloWorld)._setProperty(Stub.USERNAME_PROPERTY, "bob");

//  ((javax.xml.rpc.Stub)__helloWorld)._setProperty(Stub.PASSWORD_PROPERTY, "password");

As you can see above, the usename and password can be set by populating USERNAME_PROPERTY and PASSWORD_PROPERTY defined in javax.xml.rpc.Stub class. If you are invoking the web service using Dynamic Invocation, you can set these properties in javax.xml.rpc.Call class. If you run the code after uncommenting those lines, you will see the following output,

HelloWorldBean#sayHello() was called by Taraba Consulting
HelloWorldBean#sayHello() user: bob
HelloWorldBean#sayHello() isCallerInRole: true

Recap

So, let's just recap what we did. We configured security on the ejb that was exposed as a web service requiring the client to be in ValidUser role. We configured security in the router servlet by protecting the url /services/HelloWorld - the url that would be used by the client to invoke the service. Again, we allowed only ValidUser to access the url. We mapped ValidUser role to the enduser group that I had already defined in LDAP. We set username and password of a user that belongs to enduser group in LDAP. Before you decide to use this method for web service authentication and authorization, I encourage you to review A word of caution section in my previous blog entry.

LIST OF COMMENTS ....


1. Written by Guest/Visitor
    Sunday, 24 June 2007
Why you disabled application security?. What will happen if you enabled it?. Do you think your client will still work?.

2. Written by Guest/Visitor
    Tuesday, 26 June 2007
where do you see it disabled? It should be enabled and the client should still work

3. Written by Guest/Visitor
    Monday, 23 July 2007
Hi, great article. Thanks for posting it! I have one question/concern: i noticed that the lines regarding setting userid and pwd in the client are NOT commented out in the ear you posted. However, even when running the client with them uncommented, the ejb HelloWorldBean#sayHello() is still spitting out the 'user: UNAUTHENTICATED" and 'isCallerInRole: false" message. Am I missing something? Thanks!

4. Written by Guest/Visitor
    Friday, 21 December 2007
I am unable to see the following... "In WAS admin console, map the security roles to LDAP groups - so that the user information can be retrieved from LDAP In configure security on the server section, I described how to create users and groups in LDAP. We will map the ValidUser role in the application to the endusers group in LDAP using WAS admin console as shown below: " There's nothing below. Thanks.

Write your comment here (support html tag):

Random Code
Random Code Verification
 
Last Updated ( Friday, 29 June 2007 )
 
< Prev   Next >
BlogSidebar
 
 

Copyright Chintan Rajyaguru
Contact me if you have any questions or comments.