Skip to main content

skip to main content

developerWorks  >  Web development | Sample IT projects  >

Preserve the security of your Project Zero and WebSphere sMash applications, Part 1: Authentication and authorization

Enable access-control based security quickly and easily

developerWorks
Document options

Document options requiring JavaScript are not displayed


Rate this page

Help us improve this content


Level: Intermediate

Todd Kaplinger (todkap@us.ibm.com), Project Zero Architecture & Development, IBM 
Simon Kapadia, Security Lead, ISSW EMEA, IBM United Kingdom Ltd
Nell Gawor (ngawor@us.ibm.com), Project Zero engineer, IBM 

20 Nov 2007
Updated 28 Feb 2008

Access-control based security of application resources is one of the core features of Project Zero. With the goal of radical simplification in mind, the developers of Project Zero Security have made an effort to simplify the enablement of security and make it quick and easy. Learn about Project Zero Security and how to create a user registry, define security rules for the application, and leverage the two most common types of authentication — basic and form-based. By the end of this article, you will have all the tools you need to build security into your Project Zero applications.

Editor's note: IBM® WebSphere® sMash and IBM WebSphere sMash Developer Edition are based on the highly acclaimed Project Zero incubator project. Project Zero is the development community for WebSphere sMash and will continue to offer developers a cost-free platform for developing applications with the latest builds, the latest features, and the support of the community.

Introduction to Project Zero security

Project Zero implements authentication and authorization. Application developers can take advantage of Zero's security by defining security rules that determine which resources are protected, by what means they are protected, and what users and groups are allowed to access those resources. Zero's authentication is based on Java™ Authentication and Authorization Service (JAAS), which allows various types of login modules to be added without changing the authentication model.

Security is part of the core feature set included with Project Zero. Because of this, the only requirement to enable security is to properly configure the user service registry-related configuration and associate the appropriate rules for each protected resource. Because this article is intended for intermediate developers already familiar with Project Zero, refer to the Developer's Guide for a complete overview of Project Zero security configuration (see Resources for a link to the guide).

What's in this article?
This article, the first of a three-part series, focuses on the specifics of how to configure access-control based security in a Project Zero application without having to change many of the default configuration parameters. It assumes that you have downloaded Project Zero and either completed the introductory tutorial or written a simple application yourself.

New to Project Zero? Project Zero provides an environment for developing interactive Web applications quickly and simply. It strives to provide a complete infrastructure for Web deployment, freeing application developers to concentrate on the business logic. To learn more about -- and download -- Project Zero, see our introductory tutorial, "Get started with Project Zero and PHP."

This article demonstrates how to create a Project Zero Application using Eclipse. The assumption is that you have already installed the appropriate Project Zero plug-ins from the Eclipse Update Site and that you know how to create a Project Zero application within Eclipse. If this is not the case, refer to the "Core Getting Started" page of the Developer's Guide before continuing (a link is available in the Resources section).

The story so far...

The application we create here is a very simple one, called StockTips. The application allows for publication of very basic stock market tips. The application works by maintaining a list of "hot stocks," which have been added by and are looked after by a stock market wizard. The wizard will often add to his list when a hot new stock appears on the market, and he will also remove stocks from the list when companies take a downturn. The list is viewed by pundits: people who are interested in what the wizard has to say, and indeed people who base their stock market buying or selling decisions based on his tips. If the wizard is good with his tips, the pundits will make money!

The application code is composed of a groovy file called tips.groovy and a view called tips.gt, each displayed in Listings 1 and 2:


Listing 1. tips.groovy
                
todos = app.todos[];
if (todos == null) {
        todos = [];
}

if (request.method[] == 'POST' ) {
        def action = request.params.action[];
        if (action.equals("Add")) {
                def items = request.params.item[];
                if (null != items){
                        item = zero.util.XMLEncoder.escapeXML(items);
                        if (null != item && item.size() > 0)
                        todos.add(item);
                }
        } else {
		    def selected = request.params.todos['*'];
                for (i in selected)
                   todos.remove(i);
        }
        app.todos = todos; 
}

request.view = 'tips.gt';
render();


Listing 2. tips.gt
                
<html>
        <head>
                <title>Stock Market Tips</title>
        </head>
        <body>
                <b>Current hot stock tips:</b>
                <br><br>
                <form name="input" method="POST">
                <% app.todos.get().each { %>
                <input type="checkbox" name="todos" value="<%=it%>"> <%=it%> <br> 
                <% } %>
                <br>
                <input type="text" name="item">
                <input type="submit" name="action" value="Add">
                <input type="submit" name="action" value="Delete">
                </form>   
        </body>
</html>

Figure 1 shows the main screen of the application:


Figure 1. Original tips application
Original tips application

The astute amongst you may notice that the application looks remarkably similar to the example todo application from projectzero.org. This is because the code has been shamelessly stolen from there, and only the view has been changed. The wizard, always in the business of saving money, has reused the example code to improve his time to market!

The problem

Unfortunately, it turns out that simply reusing the todo application as-is wasn't the best idea. The way that the todo application works is that anyone who accesses the application URL can add or delete stocks. This was great at the beginning, when only a few friends were using it to share in the wizard's cleverness, but as the circle of pundits grew, malicious pundits began to appear, shown in Figure 2 These individuals would access the hot stocks, write down the tips for themselves to make some money, and then they would remove the good tips to keep to themselves — or even worse — provide some that they made up!


Figure 2. Maliciously modified tips application
Image of maliciously modified tips application

So, the wizard decided to do something about this problem, so he started reading up on Project Zero security.

The user registry

To authenticate users, a list of users must be stored in a user registry. Project Zero provides the "user service" library, which gives an extensible framework for accessing user registries. Supported registry types include text-based and LDAP (directory) registries, but the user service can be extended to create a custom user registry if that requirement exists. Your choice of registry type depends on your requirements and environment:

  • The text-based registry is suitable as a development-time registry.
  • LDAP is recommended for production, where enhanced reliability and security are important.
  • Custom user registries can be used to integrate with other registry systems.

This article uses a file-based user registry.

Creating a file-based user registry

Because configuring LDAP can take time and requires a certain level of expertise, Zero has provided another form of user registry that is file-based. To be able to create, update, and add users for testing purposes, the zero.core.webtools project provides a Web-based administration console for administering users. For those not familiar with Eclipse Webtools, the zero.core.webtools package provides a set of useful utility functions for Zero application developers to use when building applications. A dependency on the webtools module is included, by default, when you create a Zero application within Eclipse. You should remove or comment out webtools before deploying your application into a production setting.

After creating a new application, validate that a dependency on zero.core.webtools exists by expanding your Zero application to see the config directory. Inside of the config directory, there should be a file named ivy.xml. Clicking on ivy.xml should result in Eclipse showing a view of the ivy.xml listing the package information. Take a look at Figure 3, for example:


Figure 3. Zero.core.webtools included in ivy.xml
image of ivy.xml, showing that zero.core.webtools is included as part of the application

The dependency list for the application should include zero.core and zero.core.webtools. If this is the case, you are ready to start creating the file-based user registry.

To start the application, right-click on the application and select Run As > Project Zero Application. See Figure 4:


Figure 4. Run As Project Zero Application
Image demonstrating selection of Run As

Once the application is started, there is an informational message logged to the console indicating the port number with which the application is associated (see Figure 5):


Figure 5. The network port will be written to the console
Image showing the port that the application is associated with

The application is now ready to accept HTTP requests. To start creating users, you can access the Web-based admin console using the hostname of the machine and the port number that was logged to the console with a server relative path of /zero/webtools/user/. Because you are dealing with defaults most of the time, the application typically will be accessible at http://localhost:8080/zero/webtools/user/. For future URLs, we will assume a server of localhost and a port of 8080.

Note: If this is the first time you have accessed the user service application for this Project Zero Application, an error will appear on the console that the user service cannot access the zero.users file. This is perfectly normal; this file will be created by the user service application and the error will not appear once the file has been created. See Figure 6:


Figure 6. Ignore the error the first time around
Image showing the error message when the zero.users file has not yet been created

The user service application console will appear, as shown in Figure 7:


Figure 7. The user service application
Image showing the user service application

You are now ready to create users and groups. For the purpose of this demonstration, we will create a number of users. The original wizard will be called wizard. The pundits who use the application will be his friends Alice, Bob, Charlie, and Dave, whose usernames will simply be their first names. We will put our wizard user into a group called wizards (so that he can easily add more wizards after the IPO), and the other users will be put into a group called 'pundits'.

Let's create the wizard user first. Under the Add User form type in wizard for UserName, supply a password (remember to use a good password!), and specify wizards for the groups (see Figure 8):


Figure 8. Add the user 'wizard'
Image showing adding the user 'wizard' via the user service application

Now, repeat the previous steps to create the rest of the users, putting them in a group called pundits. Create a userid for each of the friends we know about: Alice, Bob, Charlie and Dave. Once you've finished creating them, the user list will look like Figure 9:


Figure 9. The final user list
Image showing adding the user list

Users and groups

What does adding user and group memberships mean? Well, on the most basic level, the data will be entered into a file called zero.users under the config directory of your zero application. Let's examine the contents of this file:


Listing 3. zero.users file
                
wizard:5f4dcc3b5aa765d61d8application327deb882cf99:wizards
alice:6384e2b2184bcbf58eccf10ca7a6563c:pundits
bob:9f9d51bc70ef21ca5c14f307980a29d8:pundits
charlie:bf779e0933a882808585d19455cd7937:pundits
dave:1610838743cc90e3e4fdda748282d9b8:pundits

The file is nothing more than a list of colon-separated values, three per line, comprising the username, an encoded version of the password, and the groups that the user is a member of. The 'file registry' is just that — a single file. It should be clear why this will likely not scale for large numbers of users!

We are now finished creating users and groups in the file-based user registry and are ready to start with defining security rules.

Defining security rules

Regular expressions
In addition to the basic option of protecting a specific URI stem, it is also possible to protect a resource by setting the URI attribute equal to a regular expression pattern. For instance, if you wanted to protect everything in your application under /protected, you could write the rule as conditions : "/request/path =~ /protected(/.*)?. The syntax uses PRCE (Perl Compatible Regular Expressions), a very powerful way of matching any desired string pattern.

Because of the power of regular expressions, it is possible to write rules that fail to protect part of your URI space. It is also easy to overlook the side effects of Project Zero's default file serving, which serves /foo/index.html (if it exists) when /foo/ is accessed. For instance, if you wrote the rule "/request/path == /foo/index.html" but someone manually accessed /foo, the latter would not be protected even though it is the same resource. For this reason, it is recommended that you group your protected resources under common areas and protect those areas and everything underneath them. The recommended pattern is therefore always "/request/path =~ /prefix(/.*)?". This should ensure you cover all the resources you want protected.

Now, our wizard has added users and groups. However, there is still nothing to say that accessing the application requires the users to log in! By default, all content is unprotected; there are no default authorization constraints. To protect your application or portions of your application, you need to define security rules. These rules specify what resources are protected; what kind of authentication they are protected by; and what users, groups, and/or roles are allowed access.

The conditions clause provides a the user with the ability to define a wide range of constraints for securing a resource. In this example, we use the Global Contect /request/path key which is context relative path that you type into your browser to reach an application, and it is also the base level of resource that can be protected in Project Zero. To protect the URI to access the application's main page, you need to define a rule matching a specified set of conditions. Open the zero.config file in the config folder of your application and add the lines shown in Listing 4 to the file:


Listing 4. Updates to zero.config
                
@include "security/rule.config"{
	"conditions" : "/request/path == /tips.groovy",
                 "authType" : "Basic",
                 "groups"  : ["wizards", "pundits"]
}


The first line precedes each security rule and imports the proper template. This lets the runtime know that you are configuring a security rule. The second line, conditions, actually defines the condition under which this security rule applies. In this case, you've chosen to protect a single URI instead of a pattern. The third line, authType, specifies the type of authentication to use. We'll use HTTP basic authentication (explained in detail in the next section) here because it requires no additional configuration. The last line, groups, says which groups can access the protected page. In this case, we will grant access to all members of the two groups wizards and pundits; that is, all of the users we have created so far, because they are all in one or another of these groups. Save the file and restart the Zero server so that it picks up the updated configuration.

Three authentication types are built into Zero: basic, form, and SSO. This article focuses on basic and form authentication. You can find more information on SSO authentication in the Zero documentation (see Resources).

Basic authentication

Note: HTTP basic authentication is a poor way of authenticating users, and you should not use it for real production deployments. One of the reasons for this is that, once a user has provided his or her username and password, it is simply encoded (not encrypted — it is encoded in a manner very easy to decode) and sent back to the server on every subsequent request to that server.

The implications of this are twofold. First, this means that any interception of any "secure" traffic with that server will reveal the user's actual username and password, which are valid until the user explicitly changes them (compare this with the typical approach of using a cookie for authentication, where the cookie is only valid for a short time, usually a couple of hours, and is useless after that). More importantly, however, is that it is impossible to log out users who have authenticated with basic authentication because every time they access a new resource, their browser provides their username and password again! The only way for the users to log out is to physically close the browser; while users should of course do this, many of them simply do not.

Credentials

Now when you try to access the StockTips application home page, your browser prompts you for credentials. To be granted access, you must supply the username and password of a valid user (in the users file) who is a member of one or other of the groups specified. See Figure 10:


Figure 10. The basic authentication dialogue
Figure 10. The basic authentication dialogue

Realms

When a resource is protected by basic authentication, the browser requires the user to present credentials in order to access it. Basic authentication is the only type of authentication built into Zero that does not require additional configuration. It is possible to explicitly specify the 'realm' presented by the browser using /config/security/realm. See Listing 5 for example:


Listing 5. Configure a basic authentication realm name
                
/config/security/realm="Private Hot Stock Tips"

This realm is then displayed by the browser when asking the user for credentials (see Figure 11):


Figure 11. The 'Private Hot Stock Tips' realm
Image showing realm

Form-based authentication

Form-based authentication provides a full-page form login. To implement it, add a new file under the public folder called login.html and paste the text from Listing 6 into it:


Listing 6. Form-based login
                
<html>
  <form method="POST" action="">
  <input type="text" name="zeroUserName">Username</input><BR>
  <input type="password" name="zeroPassword">Password<BR>
        
  <input type="submit" value="Submit"/>
  </form>
</html>

Of importance in Listing 6 are the names of the username and password fields. Zero uses the names to identify these fields when the form is posted. Next, edit zero.config by adding the stanza shown in Listing 7 to provide the location of the login form you just created:


Listing 7. Update zero.config to refer the form
                
@include "security/form.config"{
	"formLoginPage" : "/login.html"
}


Also, change the line authType : "Basic" to authType : "Form" in the security rule defined earlier and restart the Zero application to pick up the configuration changes. Now, when you access your application at http://localhost:8080/tips.groovy, you are presented with the form you created. If you enter a valid user's credentials again, you should be able to access the page. Figure 12 shows the login form:


Figure 12. The login form
Image showing login form

Form-based authentication represents a significant improvement over HTTP basic authentication, from several angles:

  • It allows you to configure the look and feel of the login page; that is, because the login form is an actual Web page, it is possible to customize the HTML in any way you choose, provided that the basic function of the form is maintained.
  • Form-based authentication results in using a cookie for authentication, rather than having the client browser send the encoded username and password with every request. This cookie, if stolen, is only valid for the length of the browser session, so the theft does not result in revealing the username and password to the thief.
  • Form-based authentication can be included on any Web page (because it is simply an HTML form that needs to be submitted to the application's URI), providing a better user experience.

Advanced authorization

So, our wizard now has authentication configured for his StockTips application, with simple authorization where users have to be authenticated to access the application. However, there is no difference at present between the 'pundits' group, whose members simply need to see the tips, and the 'wizards' group, whose members need to make updates. In order to make an authorization decision such as this, we can specify separate authorization constraints for different actions, and indeed make programmatic authorization decisions based on group memberships when choosing what to display.

The Project Zero community
Take a stroll around the Project Zero Web site and see how Project Zero provides a powerful — but radically simple — development and execution platform for modern Web applications. The active community discusses project development, provides help to developers, and wants to hear your ideas!

Authorization constraints

As well as protecting access based on URI, as described previously, it is also possible to protect resources by the HTTP method. For instance, if you wanted a resource to be open to HTTP GET requests but protected from PUT, POST, and DELETE requests, you could add an additional clause to the conditions line (conditions are separated by && for 'and' clauses || for 'or' clauses) of ( /request/method == [PUT|POST|DELETE]) and the rule would apply only to those methods.

Because the StockTips application uses a GET request to display information but a form POST to accept updates, we can use this functionality to ensure that only the correct groups are authorized to update information. Modify the zero.config file to allow access to HTTP GET requests for all groups, but HTTP POST requests for only the wizards group. Because this will be the final update to the zero.config file, the entire file is shown in Listing 8:


Listing 8. final zero.config
                
/config/http/port=8080

@include "security/form.config"{
		 "formLoginPage" : "/login.html"
}

@include "security/rule.config"{
		 "conditions" : "(/request/path == /tips.groovy) &&  (/request/method == GET) ",
|-------10--------20--------30--------40--------50--------60--------70--------80--------9|
|-------- XML error:  The previous line is longer than the max of 90 characters ---------|
                 "authType" : "Form",
                 "groups"  : ["wizards", "pundits"]
}
@include "security/rule.config"{
		 "conditions" : "(/request/path == /tips.groovy) &&  (/request/method == POST) ",
|-------10--------20--------30--------40--------50--------60--------70--------80--------9|
|-------- XML error:  The previous line is longer than the max of 90 characters ---------|
                 "authType" : "Form",
                 "groups"  : ["wizards"]
}
/config/security/realm="Private Hot Stock Tips"


This configuration means that everyone in the groups wizards and pundits will be able to access GET on the application URL (/tips.groovy), but only members of the 'wizards' will be able to POST. Therefore, only wizards will be able to make changes. In addition to restricting access to certain groups, you can also restrict access to certain users and roles (for more information on roles, see the Project Zero documentation link in Resources). The special group ALL_AUTHENTICATED_USERS can be used to grant access to all users that log in successfully.

Programmatic authorization

Our wizard is now the only one able to make changes to stock tips, and his pundits are the only people able to read them. This scenario is almost perfect, but not completely perfect yet. While the pundits won't be able to actually make changes, the application's interface still includes the fields to do so, including Add, Delete, and so on. Of course, clicking Add or Delete won't work for people who are not in the wizards group because that individual won't be authorized to access a form POST, but it would still be better not to display the functionality at all.

Conveniently, Project Zero lets you programatically identify the authenticated user, and thus make a decision in your code based on the username, the groups the users are a member of, or the roles in which they reside. After successful authentication, the following fields are available for use within the Global Context:

/request/subject#remoteUser
/request/subject#groups

In our StockTips application, the wizard can use this information to decide whether or not to display the graphical interface widgets for adding and deleting tips on the application Web page. Replace the line request.view = 'tips.gt'; with the contents of Listing 9:


Listing 9. Update StockTips to display different views based on groups
                
if(request.subject.groups[].contains("wizards")){
	request.view = 'wizards.gt';	
} else if(request.subject.groups[].contains("pundits")){
	request.view = 'pundits.gt';
} else request.view = 'tips.gt';


Next, add two new views: a wizards.gt, which is identical to the original tips.gt, and a pundits.gt, which is significantly cut down (see Listing 10):


Listing 10. pundits.gt
                
<html>
  <head>
    <title>Stock Market Tips</title>
  </head>
  <body>
    <b>Current stock tips:</b>
    <br>
    <ul>                
      <% app.todos.get().each { %>
      <li><%=it%></li> 
      <% } %>
     </ul>
    <br>
  </body>
</html>

Now, when you log in as the wizard, who is in the wizards group, you see the full application, complete with the buttons to add and remove stock tips (see Figure 13):


Figure 13. Logged in as the wizard, in group 'wizards'
Image of final tips application as wizard

However, when we log in as alice, who is only in the pundits group, we see the pared-down version of the application (see Figure 14):


Figure 14. Logged in as alice, in group 'pundits'
Image of final tips application as alice

Conclusion

This article has covered all the steps required to enable the security runtime in Project Zero and protect your applications. We discussed setting up a user registry and two ways to authenticate users (basic and form-based). We defined security rules for declarative authorization and programmatic authorization by retrieving user, group, and role information from within the application. Stay tuned for Part 2 of this series, which will describe leveraging LDAP with Project Zero Security, and Part 3, which will describe leveraging OpenID with Project Zero Security.

Share this...

digg Digg this story
del.icio.us Post to del.icio.us
Slashdot Slashdot it!



Resources

Learn
  • Refer to the Project Zero Developer's Guide for a complete overview of Project Zero security configuration.

  • Because this article assumes that you have already installed the appropriate Project Zero plug-ins from the Eclipse Update Site and that you know how to create a Project Zero application within Eclipse, if you haven't already done so and need to do so, refer to the Core Getting Started page of the Developer's Guide before continuing.

  • Join the Project Zero community and see what all the buzz is about!

  • Browse the developerWorks Web development zone to find tools, code, and resources to get you started developing Web 2.0 applications today.

  • The developerWorks Ajax resource center is packed with information for all skill levels to help you build Ajax into your applications and dramatically improve your user's Web experience.

Get products and technologies
  • Download Project Zero and start applying the skills learned in this article.


Discuss


About the authors

Todd Kaplinger

Todd Kaplinger is a senior software engineer in IBM Software Group, currently working as architect and team lead of the Security team for Project Zero. Todd is an expert in Web-based technologies such as JSP, Servlet, and PHP, with a recent focus on emerging Web 2.0 technology and its impact on the enterprise. Todd is currently a member of the expert group responsible for JSR 223: Scripting for the Java Platform and is also a member of the Open AJAX Alliance with an interest in interoperability between various Ajax framework implementations on security. Todd acted as team lead and architect of IBM WebSphere Webcontainer and Remote Request Dispatcher (RRD) project and participated in the JSR 154 Servlet 2.5 specification as the IBM representative in the Servlet Expert group.


Simon Kapadia

Simon Kapadia is the Security Lead for IBM Software Services for WebSphere (ISSW) in EMEA (Europe, Middle East, Africa). He works on designing and implementing large distributed computer systems for IBM customers. Simon holds a Bachelor’s degree in English and Drama and a Master’s in Computing Science. He has owned a computer since six years of age and has turned a lifelong hobby into a career. Prior to joining IBM, Simon developed software for digital exchanges at Bell Laboratories, managed networks and Web applications at an ISP, and supported and consulted on DCE, DFS, and Encina for Transarc Corporation. You can reach Simon at simon.kapadia@uk.ibm.com or via his public Web site at http://www.kapadia.pl.


Nell Gawor is an advisory software engineer for IBM in Research Triangle Park, North Carolina, on the Project Zero team. She received a Masters Degree in Computer Science from the University of Illinois at Urbana-Champaign.




Rate this page


Please take a moment to complete this form to help us better serve you.



YesNoDon't know
 


 


12345
Not
useful
Extremely
useful
 


Share this....

digg Digg this story del.icio.us del.icio.us Slashdot Slashdot it!



Back to top


Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the United States, other countries, or both. Other company, product, or service names may be trademarks or service marks of others.