ptg 212 Chapter 9 Security Model Figure 9.4 Main landing page At this point, our application is ready to serve pages using the HTTPS protocol. Let’s create a simple index.get landing page to verify that our SSL certificate is recognized. Create a new file called /public/index.gt, whose contents are shown in Listing 9.2. Listing 9.2 Main Landing Page (/public/index.gt) <html> <head> <title>sMash Security</title> </head> <body> <h1>Welcome to the Security Application</h1> <h3>This page is not protected</h3> <h2>Try going to a <a href="<%= getRelativeUri(‘my/index.gt’) %>">Protected page</a>. </h2> </body> </html> Open your browser to https://localhost:8443/ (note the https protocol, and the special port number we defined earlier). You should first get a warning from your browser that the connection is untrusted, due to using a self-signed certificate. This is a good behavior, as it’s validating that WebSphere sMash was able to process the certificate, and your browser just doesn’t approve its validity. Click through the warning to acknowledge this issue and optionally add this as an excep- tion to your browser. You should then be taken to our main landing page, as shown in Figure 9.4. We’ll build on this shortly to add a secured page, as well as login and logout pages. That wasn’t so bad, was it? Next, let’s go over user authentication and how we actually protect various resources in our application. Download from www.wowebook.com ptg SSL Configuration 213 Enabling Security A single setting enables security within a WebSphere sMash application. A secure application by default protects all resources addressable by URL, and simply requires users to be authenticated, but no other restrictions are applied. We’ll walk through fine tuning which resources should be protected, and for which users and groups, later in this chapter. To enable security, add the line shown in Listing 9.3. This provides a single location to quickly disable security during debug- ging, by just commenting out this one line, regardless of any other security-based configurations defined in the configuration. Listing 9.3 Enable Security Configuration Setting # # Security Config # @include "security/enableSecurity.config" Application Secret Key Each application that will enable security needs to have a secret key defined. This key is used to provide a seed for encrypting sensitive data. By utilizing a secret key value within the application, the potential for Cross Site Request Forgery (CSRF) 1 and other external attack vectors is greatly reduced. The actual value of the secret key has no meaning, other than it is nearly impossible for an attacker to guess it to use in an exploit. To create a secret key, run the zero secretkey command from within your application’s directory. Alternately, if you are using the AppBuilder, select the Console tab, and run zero secretkey at the prompt, as shown in Figure 9.5. In either case, the results will be an encoded secret key string. Copy this value and add it as a value to the /config/security/secretKey entry in the application’s zero.config file, as shown in Listing 9.4. Listing 9.4 Adding a Secret Key to the Application’s config File # # Security settings # @include "security/enableSecurity.config" /config/security/secretKey="iZBIC6dB2pWBURIW/UEVSw==" For advanced scenarios where you may want to have two or more WebSphere sMash appli- cations share common tokens, generate a secret key in one of the applications, and copy this com- mon value to each of the other applications. 1 CSRF: http://en.wikipedia.org/wiki/Cross-site_request_forgery Download from www.wowebook.com ptg 214 Chapter 9 Security Model Figure 9.6 Basic authentication login prompt Figure 9.5 Create a secret key in AppBuilder’s console. Authentication Types All resources in WebSphere sMash are protected by URLs. Patterns can be used to define which URLs require authentication. When you define a rule for a URL or URL pattern, you may also limit it to be accessed by certain users and/or groups. The default value for any authenticated user is membership within the group: ALL_AUTHENTICATED_USERS. The default security rules, when enabled as described previously, restrict access to all URL patterns. Most applications will probably want to allow anonymous users to at least access a welcome page or other introductory pages, which is explained further later in the chapter. There are a few different methods for authentication within WebSphere sMash, as described in the following sections: 1. Basic authentication prompts the user with a simple browser-styled pop-up similar to Figure 9.6, which will request the username and password when a non-authenticated user requests a protected URL. See RFC 2617 2 for details on basic authentication. 2 RFC 2617: http://tools.ietf.org/html/rfc2617 Download from www.wowebook.com ptg SSL Configuration 215 Resource Requested Resource Served Protected URL? Valid Tok e n? User Authorized? Login Successful? N Y Y N N NY Y Request User Credentials (Login) User Token Generated Status 401 Unauthorized Status 403 Forbidden Figure 9.7 General authentication logic flow 2. Form-based authentication provides a better user experience in that when a protected resource is requested, a custom login page is presented to the user that can be tailored to match the overall business styling of the rest of the application. In this setup, we’ll be using form-based authentication, which is a common means for defining how a user is authenticated against a user registry. Other types of authentication include single-sign on services, OpenID, and custom programmatic solutions. We’ll touch on these other authentication types and features later in the chapter. The generalized authentication flow for the types of authentication mentioned previously is shown in Figure 9.7. Download from www.wowebook.com ptg 216 Chapter 9 Security Model Table 9.1 URL Protection Values Member Description Default conditions This defines the URL-based resource(s) to be protected. You may also define the HTTP methods (GET, POST, and so on) allowed as well. ”/request/path =~ /(.*)?” This pattern defines all possible URL paths. users Array of user IDs allowed to access this resource. All authenticated users may access this resource. groups Array of groups whose members are allowed to access this resource. [“ALL_AUTHENTICATED_USERS”] This is a pseudo-group that all members belong to. roles Array of roles whose members are allowed to access this resource. Unset realm Default realm used for basic authentication. This is an advanced LDAP environment setting. Unset Form-Based Authentication Configuration Settings Table 9.1 lists the various settings available to define the form-based authentication environment within the WebSphere sMash application. Each of these is a member of the /config/security object in the zero.config file. Let’s put these settings into the zero.config file for our application. In the configuration fragment shown in Listing 9.5, we define the following settings. In the first stanza, we define a new rule that protects any URLs that are located under the /my tree. When an URL matching this pattern is requested from the browser, the basic authentication mechanism checks for a valid token and if not found will request that the user log in. Upon successful authentication, the user is checked to see if he is a member of the listed groups for authorization. We are allowing any authenticated user, based on the default pseudo-group called "ALL_AUTHENTICATED_USERS". The second stanza defines the form page URL, which in our case is located at "/login.gt". Download from www.wowebook.com ptg Login Form 217 Listing 9.5 Form-Based Authentication Configuration # # URL Protection # # Conditions define what path(s) are to be protected (req login) # Groups list the groups that are allowed access to this url path @include "security/rule.config" { "conditions": "/request/path =~ /my(.*)?", "authType" : "Form", "groups" : ["ALL_AUTHENTICATED_USERS"] } # Login form @include "security/form.config" { "formLoginPage" : "/login.gt" } Login Form Next, we need to create our login page that will be used exercise the security configuration. By using basic authentication, if the user does not have a valid token defined, he will be redirected to the defined login page. The login page itself consists of three fields within a POST form. You can dress up this form as desired to meet any stylistic needs. The basics of this page consist of that shown in Listing 9.6. Here, we have a standard HTML form with a POST method. There are two required input fields: "zeroUserName" and "zeroPassword". There is also an optional third field called "postLoginTargetURI"; if set, this field will be used as the target page when the login is successful and is used for the redirect target. If this field is not present, the originally requested resource will be the target page used after successful authentication. Listing 9.6 Login Form Page (/login.gt) <html> <head> <title>Login Test</title> <style> @import "<%=getRelativeUri(‘/theme.css’)%>"; </style> </head> <body> Download from www.wowebook.com ptg 218 Chapter 9 Security Model <% if( zget("/request/headers/in/Referer") =~ zget("/request/uri") ){ %> <div class='error'> <h2>Invalid user ID or password</h2> Please verify your ID and password and try again. </div> <% } %> <p>Login using your normal user ID and password:</p> <form method="POST" action="" name="loginForm"> <! optional hidden field to force the target redirect after login > <! <input type="hidden" name="postLoginTargetURI" value="/my"> > <label for="zeroUserName">User ID:</label><br/> <input type="text" name="zeroUserName" size='20' /><br/> <label for="zeroPassword">Password:</label><br/> <input type="password" name="zeroPassword" size='12' /><br/><br/> <input type="submit" value="Submit" /> </form> </body> </html> If you examine the code on the login page, there is an obscure check to determine if the referring page is the same as this page. This is done to determine if the user has been to the login page already. If a user attempts a login and enters a bad username or password, the login fails, and the user is returned to the login page. Another error condition that we need to tackle based on the flow diagram is when the user successfully logs in but is not authorized to view the resource based on the URL in the configura- tion settings. In this case, a 403 error will be returned by the login process. To handle this situa- tion, we have to create a /app/errors/error403.gt file to inform the user of what went wrong. You can see a sample of this in Listing 9.7. You should provide the user with a means of Download from www.wowebook.com ptg Login Form 219 returning to a clean state, such as a link to the application’s home page, when this error condition is encountered. Listing 9.7 /app/errors/error403.gt <html> <head> <title>Login Error</title> <style type="text/css"> @import "<%=getRelativeUri("/theme/style.css")%>"; </style> </head> <body> <div class=’error’> <h2>Unauthorized access (Code: 403)</h2> You are not allowed to access this portion of the application. Please contact the application owner and request access. </div> </body> </html> Knowing Your Users When you allow a user to access sensitive information, it is important to know who that person is. It is important to maintain various levels of control over who can access different types of documents. This control is done through authorization, where typically the user will log into the application with a uniquely identifying username and password. When you know who you are dealing with, you can also determine other information for this user, such as his name and what groups he belongs to. You can then use this information to provide a custom experience tailored specifically to his rights, privileges, and preferences. There are many different systems available for managing users. Some of the more common include the Lightweight Directory Access Protocol (LDAP), such as IBM’s Tivoli® Directory Server, Microsoft® Active Directory, and some relatively new solutions, such as OpenID. WebSphere sMash uses standard Java Authentication and Authorization Service (JAAS), to authenticate users and also provides a minimal file-based user management solution for basic user authentication. We’ll start out by building a simple file-based user authentication solution. After this is fully built and working, we will then modify the solution to use an LDAP server and take a peek into defining an OpenID environment as well. Download from www.wowebook.com ptg 220 Chapter 9 Security Model Figure 9.8 Creating users using the file-based zero user command Basic Zero Users Configuration By default, WebSphere sMash provides an embedded user registry that can be used for small to medium applications or testing that does not require an external authentication resource. This file-based service maintains a list of users, their passwords, and the groups they belong to. The file is called zero.users and is located in the application’s /config directory. To create or edit entries in the user service, run zero user from the command line or from the command prompt within AppBuilder. A series of prompts guide you through the process of creating or editing users, as shown in Figure 9.8. For advanced usage, you can supply all the parameters on the com- mand line, which would facilitate creation of users through a script or other build process. After you have created your users and assigned them a password and group memberships, the zero.users file will be created. Groups can be used to restrict users based on some arbitrary Download from www.wowebook.com ptg Login Form 221 Figure 9.9 Listing of zero.users file collection, such as team membership or management level. Figure 9.9 shows the resulting user file after creating a couple users. Additional Files for Our Application Before we can test out this secure application, we need to create a couple more files. The first is a protected index page, and the next is a logout page for when the user actively clicks a logout link. The first page we need to create is our protected page, located at /public/my/index.gt. The contents of this file are shown in Listing 9.8. On this page, we can be assured that the user is logged in successfully, and we then show some details about the user. As you can see, we are lim- ited to the username and the groups of which he is a member. If you need more details than that, you need to step up to an LDAP or similar solution or create your own custom user profile within the application itself to retrieve this kind of information from an external identity resource—for example, a directory server (LDAP server) or even your self-built identity information database. Listing 9.8 Secured Landing Page (/public/my/index.gt) <html> <head> <title>Protected Page</title> </head> <body> <% Download from www.wowebook.com . ptg 212 Chapter 9 Security Model Figure 9.4 Main landing page At this point, our application is ready to serve pages using the HTTPS protocol. Let’s create a simple index.get landing page. within a WebSphere sMash application. A secure application by default protects all resources addressable by URL, and simply requires users to be authenticated, but no other restrictions are applied Basic authentication login prompt Figure 9.5 Create a secret key in AppBuilder’s console. Authentication Types All resources in WebSphere sMash are protected by URLs. Patterns can be used to define