Achieve easy front end authentication with DataPower and HTML form-based login
This content is part # of # in the series: Conquering complexity
This content is part of the series:Conquering complexity
Stay tuned for additional content in this series.
Each installment of Conquering complexity addresses a common issue related to security that can be resolved or simplified using IBM WebSphere DataPower Appliances and other IBM technologies.
HTML forms-based login authentication is commonly seen on the Internet. A web site displays an HTML form into which a browser user will provide credentials (such as a username and password) that are then used to authenticate the user’s access to a web application. IBM WebSphere DataPower Appliances have supported HTML forms-based login since version 3.8.1 within the web application firewall object. This capability was included as a generic mechanism within the AAA (authentication, authorization, audit) action in firmware version 5.
The most commonly deployed use case we see is for the DataPower HTML form login functionality to be deployed in front of a Java™ EE application running on IBM WebSphere Application Server. This is a great use case; DataPower can generate a Lightweight Third Party Authentication (LTPA) token, which is an IBM proprietary token format that WebSphere Application Server understands, and can thus propagate the user identity to the application server so that it can be used, for example, to make authorisation decisions or for audit purposes. Protecting applications on WebSphere Application Server, however, is not the only use for HTML form-based Login.
This article presents an example of putting DataPower in front of an existing unauthenticated web site. In this simple example, the back end is a set of static HTML pages that do not need propagation of authentication information; we simply need to be sure that you cannot access the data on the web site without first having logged in with a username and password. Future articles will share more about how — once you have an authenticated the user — you can pass that information on to a back end system in a secure manner, as part of an end-to-end application security solution. DataPower is extremely flexible and is capable of generating many different kinds of security tokens, making it a great choice for a front-end authenticating web proxy for many different types of back ends.
This article is based on DataPower firmware release 220.127.116.11.
The DataPower implementation of HTML forms-based login is originally based on the Java EE specification, as anyone investigating it will quickly realise when they see the default names of the form parameters in use. The vast majority of the work of a forms-based login configuration is carried out in the DataPower AAA Extract Identity (EI) step, which might seem counter-intuitive to those familiar with the framework. The reason for this is to provide a single point of control for the login form, and this point of control is known as the HTML forms login policy. Let’s take a look at a simple example of such a policy.
HTML forms-login policy
The HTML forms-login policy used for this article is shown in Figure 1.
Figure 1. An HTML forms login policy
Let’s examine each section of this policy.
- Source for Form-processing configuration tells the runtime that in this instance you will use static HTML files to serve the HTML forms required for login, logout, and error pages. It is also possible to dynamically generate the HTML forms using an XSL stylesheet, which gives a layer of flexibility by enabling the login form to tailor its output based on run time parameters; for example, a configuration that is proxying multiple applications could use a stylesheet to examine which application the user is trying to access and display an appropriately personalised look and feel. In this exercise, however, there is no requirement for dynamic generation.
- Next is the Redirect URL Type. For this example, you will use the Host redirect type; this tells the runtime that when it builds a URL redirection to one of your custom pages (such as the login page), it should use the value of the HTTP host header as the stem of the URL to which it redirects. In some advanced use cases, for example, if this is the second in a chain of reverse proxies, this might not be appropriate. In that instance, you might want to instruct the runtime to use the URL-in service variable instead, which is the other option in the drop-down; this will instruct the runtime to base the request on the value of the DataPower variable var://service/URL-in, which will typically use the IP address that the request came in on. In the majority of cases, Host will be a better option, especially when load balancing is in the picture.
- The first indicator in this section, Use SSL for Login, defines whether you want to use SSL for the authentication; that is, whether the URL you redirect to should connect to a separate port (typically 443 on the Web) using HTTPS. It is usually not good practise to use SSL only for authentication; rather, if there is a requirement for SSL, then all traffic should be encrypted. Therefore, you would typically set this option to off, and ensure that the gateway you configure only accepts traffic over SSL. If you use a stylesheet to generate your login forms, the SSL option doesn’t appear here, and you should also ensure that your gateway only accepts traffic over SSL. You should always use an HTTPS front side handler. For this example, we’re showing everything over HTTP so that you can download the example and import it without having to deal with certificates, but it is strongly recommend that everything use SSL.
- You might think that with a name like Enable Session Migration that this indicator is only used when you have multiple appliances in a load balanced configuration. That is true to an extent; it enables the use of a shared secret key (symmetric key encryption) such that all appliances using the same key are able to decrypt the cookies used. However — and this is really important — if you do not select Enable Session Migration and specify a key, the cookies used will not be secured. You must in all configurations specify a shared secret key object, which will be used to encrypt the cookies, otherwise your cookies will not be secure.
- Client-side URL fragments
This is how you tell the runtime what URIs it should use when redirecting to your HTML form-based login pages. You configure the login, error and logout pages, and when a login, logout or authentication error occurs the runtime will generate the URL based on these URIs. The Default URL configured here is the URI that the appliance will redirect the user to after authentication, if he accessed the login page directly; that is, by clicking on a link directly to the login page or by typing the full login page URL into his browser rather than trying to access a protected resource which redirected him to the login page.
- Location of HTML pages
- Login form properties
The contents of this section will appear familiar to anyone versed in Java EE applications, at least with its default settings (which have been left alone for this article). These settings tell the runtime what parameters it should look for when the login form is submitted in order to retrieve the username and password supplied, and to find the original URL that the user tried to access (assuming he was redirected to the login page after trying to access a protected resource) and the POST action that the login form used. Any values that you like can be filled in here — however, whatever values are used here must also be used in the HTML of the login form itself. Be aware that the URI used in the POST action must exactly match the string – for example, if you use the default of
/j_security_check, a form submitting to
/services/j_security_checkwould not work.
This final section defines the length of time during which the authenticated user session will be valid. This includes an Inactivity Timeout, by default 600 seconds (10 minutes), and a Session Lifetime with a default of 10800 seconds (half an hour).
That’s the definition of the HTML forms login policy. The next section looks at how you tell the runtime to actually use the policy use the AAA policies.
In order for the DataPower runtime to apply the HTML Forms Login Policy defined above, you will create two separate AAA actions. The first of these will be used to serve the HTML forms themselves, while the second will handle enforcement of the authorization rules and redirection to the forms when necessary.
Both AAA policies use the same method for the identity extraction phase, as shown in Figure 2.
Figure 2. Identity extraction mechanism
This configuration tells the AAA policy to use HTML forms-based authentication, and enables you to specify the HTML forms-based login policy to use. It is important that both AAA actions use the same HTML forms-based login policy; if they do not, it will not work. The names of the cookies used to maintain the authenticated session incorporate the name of the policy, so if the policies used are different, then the login process will fail.
Let’s take a look at the AAA policy used to serve the HTML forms. The policy, in this example called hfbl_example_forms, is special; the only processing required is in the identity extraction stage, and so everything else in the policy must allow the request to proceed. It does not require authentication or authorisation as the form is a public document and available to everyone. For example, the Authentication stage of this policy is shown in Figure 3, and it simply passes the identity token on to the Authorisation stage.
Figure 3. Authentication stage of the form-serving AAA policy
Likewise, the Authorisation stage of the policy, shown in Figure 4, is configured to always allow all requests through, relying on the HTTP form-based policy in the identity extraction stage to perform the necessary actions to serve the pages.
Figure 4. Authorisation stage of the form-serving AAA policy
The second AAA policy in use, called hfbl_example in this example, is where the actual enforcement happens. This policy is used in front of all other requests that go through the proxy, and ensures that anything which is not explicitly accepted by an earlier rule (as shown later in the definition of the processing policy) will have been appropriately authenticated and authorised.
The most important part of understanding the AAA policy used for enforcement is that this is where you perform your actual AAA processing. This policy will use the HTML forms-based login identify extraction method to retrieve the username and password and to ensure that all subsequent requests have the correct secure session information — but you are free to configure all of the other sections as you wish. For example, the policy might query an LDAP server to authenticate the username and password provided, or it might run a custom stylesheet to integrate with your own internal authentication system. Likewise, the authorisation step can be customised or integrated with any of the out of the box authorisation mechanisms available. This flexibility is a big part of the popularity of DataPower, and why it makes a very suitable authenticating reverse proxy for web traffic.
In the example, we have chosen to simply authenticate the username and password provided against an on-box list of usernames and passwords in XML form, called a AAAInfo file (a description of this file format can be found in the DataPower documentation). A sample file is provided in the store: directory on the appliance and is shown in Figure 5; this will be used for this example as a quick way of being able to authenticate.
Figure 5. Authentication stage of the enforcement AAA policy
So far, we’ve defined an HTTP forms-login policy and created two AAA policies that use it. All that’s left is to create a DataPower proxy configuration to allow traffic through the appliance to your back end system. You will do this by using a multi-protocol gateway configuration.
The multi-protocol gateway used here is shown in Figure 6.
Figure 6. Multi-protocol gateway
The multi-protocol gateway is configured to be an external
front end to your internal server — in this example,
http://internal.protectedweb.co.uk, a (fictional)
internal system that you are about to connect to the Internet.
The multi-protocol gateway is configured with a static back
end, and provides an HTTP front side handler (listening on port 80, the default web port) for its front end. (Again, if this were the real world, you would be listening on port 443 and running over SSL.)
The key to the multi-protocol gateway is the multi-processing gateway policy, which tells the appliance how to behave when dealing with traffic, but before we go through the policy there are a couple of important settings for your multi-protocol gateway that you need to understand.
- First of all, because you are dealing with web traffic, the
vast majority of requests will be HTTP GET requests. The
default front side handler configuration is tailored to web service traffic, which uses a POST request, so by default it does not accept HTTP GETs. You therefore need to modify the configuration to accept GETs, as shown in Figure 7. Be aware that even though this is a static web site (which is likely to be almost exclusively GETs), you must leave the POST method enabled because your login form uses an HTTP POST. In theory, you could write the login form to use an HTTP GET with the data passed as request parameters, but this is seen as a bad practise in the industry (it’s all too easy for someone to bookmark a URL with the embedded username and password, so please don’t).
Again, while an HTTP front side handler is shown in this example, you must use an HTTPS front side handler in any real application.
Figure 7. Front Side Handler configuration
- Second, again, because you are dealing with web traffic,
Figure 8. Request and response types set to Non-XML
Now we can look at the multi-protocol gateway policy, shown in Figure 9.
Figure 9. Multi-protocol gateway policy
As you can see, there are three request (Client to Server) rules configured in the policy. Let’s examine each one.
- The first rule, hfbl_example_unauthenticated, contains a match action which is shown in Figure 10.
Figure 10. The match rule for unauthenticated requests
This match rule, which matches Boolean Or Combinations (exactly one of the conditions can match), will pick up on all of the exact URIs that you will permit through to the back end without the user having to log in. This is effectively a whitelist – if the request isn’t on this list, it will not be allowed through. The whitelist allows the main site CSS file, master.css, which is actually used by your HTML forms. It also allows the requesting of the favicon, because browsers rather irritatingly request this constantly (you might wish to match with PRCE for .*/favicon.ico, to pick up any favicon requests elsewhere in the application pages, although there’s no harm in enforcing authentication on them; the main reason for doing it here is so that the favicon can also show in the login form page). The list contains exactly one HTML page, the home page of the server (matched as either / or /index.html); a decision was made in this example to allow the main page to be visible to users without them having to log in. This is a relatively common practise; the page can, for example, provide information for users on how to sign up for the service. In our instance, the page simply provides a link to the login form.
Notice that the whitelist of files does not include the HTML forms (login.html, error.html and logout.html) themselves; these will be served via the HTTP forms login policy instead.
- The next rule in line is called
hfbl_example_serve_forms, and its purpose is to serve the HTML forms themselves. It uses a Match with PRCE (Perl Compatible Regular Expression) match action, shown in Figure 11.
Figure 11. The match rule for HTTP Forms
Notice that the URL match here will match your three HTTP forms, with an optional request parameter of originalUrl, and nothing more. This is because this rule does nothing except invoke your form serving AAA action, hfbl_example_forms. This action will serve the login, logout, and error pages; because of the configuration of your HTML Forms Login Policy it will retrieve them from the back end server. It will not request any data from the back end other than this; as discussed earlier, you could configure the appliance to store these forms locally instead, or dynamically generate them using XSLT, if desired.
- The third and final request rule is
hfbl_example_request_rule. This rule has a match action called matchAll that will match all requests that are not matched by previous rules. The actions on this rule are shown in Figure 12.
Figure 12. The request rule for all other requests
There are two important actions on this rule after the match.
- First, you run an action called Convert Query Params to XML. This action will take any HTTP query parameters provided from an incoming request (such as the HTTP form POST used for login) and present them as an XML data structure, so that the AAA action can interrogate and use them.
- The second action is your AAA action for enforcement. Since it uses the identity extraction method of HTML forms-based authentication, referencing your HTML forms-login policy, it requires either a HTTP form POST containing a username and password or a relevant security cookie for every request, and once it extracts the user’s credentials from one of these it runs through the AAA steps. Thus we can be sure that each and every request that is permitted through by the AAA policy is legitimate; this is your access control enforcement point.
Putting it all together
You now have your configuration set up and put together. Let’s take a look at it in action.
First you will make a request to the web site, in a new browser window (try using Google Chrome in incognito mode to make sure that you have a clean environment with no cookies). Use the URL of the main page in your browser window and connect to the DataPower multi-protocol gateway, where the hfbl_example_unauthenticated rule allows the request to go through to the back end, giving you the main index.html page, as seen in Figure 13.
Figure 13. The main web page of your site
The main page has a link to click on, which leads to the home page. When you click the link, it hits the hfbl_example_serve_forms rule which sees that you have no authentication and redirects you to the login.html page, as seen in Figure 14.
Figure 14. The login page
Notice that the originalUrl parameter has been filled in for you – once you log in, you will be redirected to the page you originally requested, home.html. Type in your username and password and click login, which performs the login by submitting your username and password to the url j_security_check (as specified in your policy). The enforcement AAA policy runs again, your credentials are authenticated, and finally a security cookie is set and you are redirected to the home page, as shown in Figure 15.
Figure 15. The protected application home page
You finally have access to your protected data. You are able to use the web site for as long as your session is valid – 30 minutes, provided you take at least one action every 10 minutes, as per the settings in your policy. Finally, when you are finished using the application, you can click the logout link, which will bring you to the logout page, as shown in Figure 16.
Figure 16. The logout page
As part of serving the logout page, the appliance has deleted the cookie used for authentication; any further access will require you to log in again.
Finally, let’s try generating an authentication error by logging in again, but this time with a username and password that is not in your authentication repository. The appliance responds with the authentication error page, as shown in Figure 17.
Figure 17. The error page
Notice that this error page is different and separate from normal DataPower error handling. It will only show up in the event of an error during HTML forms based processing; any error elsewhere will go through normal DataPower error processing, thus a real-world processing policy should use error rules as normal.
What’s in the cookie
When you authenticate via the DataPower HTML forms-based login, a cookie is created. You can see this cookie, for example, by using the Google Chrome developer tools, as shown in Figure 18.
Figure 18. The forms-based login cookie
This cookie is named based on the name of the Forms-Based Login Policy, so in this example it is called forms.hfbl_example.session. The cookie is a base64 encoded string, which contains encrypted data. The data inside the cookie includes the username and password provided in the original login, along with a creation timestamp. The data is then encrypted using the Shared Secret key specified earlier, under Enable Session Migration.
Using a web application firewall configuration
Why not use a web application firewall configuration? You could have. The web application firewall could replace the multi-protocol gateway configuration described in this article. Instead of a processing policy, you would create a set of web request profiles, which work in a similar manner. The web application firewall configuration object also has other features that could be useful for fronting web applications; for example, out of the box it can do things like automatically sign and encrypt cookies from back end web applications. That said, for a simple use case like that shown in this example, the multi-protocol gateway is a simpler configuration and a useful teaching tool. In practise, many users choose to use the multi-Protocol gateway for fronting their web applications because they are familiar with its configuration.
What isn’t covered here? Well, a lot. There is much more to designing a fully secure end-to-end externally facing system than adding an authenticating reverse proxy server, no matter how wonderful that reverse proxy server might be. Some examples include:
- Propagating identity to the back end system. Maintaining a fully fledged security context at the back end is important; if the application at the back end can be certain of the identity of the user, it is able to make very fine-grained authorisation decisions, to audit the actions of the user and more.
- Encryption of connections to the back end system. The use of SSL for connections to the back end server should be encouraged; once credentials begin to be passed over this connection, it becomes a weak point.
- Authentication of connections to the back end system. How does the back end know that the requests coming to it are indeed from the reverse proxy?
- And there are many, many more.
A good starting point for thinking about designing a secure infrastructure is presented in these WebSphere Application Server security hardening articles.
The author would like to thank Shiu-Fun Poon, Ozair Sheikh and John Rasmussen for their assistance and comments.
- Advanced security hardening in WebSphere Application Server V7, V8 and V8.5
- WebSphere DataPower Information Center