JAAS and the HTTP Session Life Cycle

by Rajesh Shah
08/22/2005

Abstract

The J2EE security model provides a robust and easily configurable approach to securing Web applications. In a typical interaction with a Web application, a user provides security credentials and the Web application then starts an authenticated session. The user is granted access to secured resources based on his or her assigned security role, and after logging out or having the session expire, the user is returned to the login page. This happens transparently, and an appropriately configured application would always expect a user to be logged on using this mechanism. However, sometimes an application needs to know that a currently logged on user's session had expired in the past. This article examines the inner workings of the BEA WebLogic Server 8.1 J2EE security framework in relation to this HTTP session behavior. In particular, it looks at how a Web application can capture an expired session event.

A Web application and source code is distributed with this article.

Introduction

The WebLogic Server security model for a Web application is based on Java Authentication and Authorization Services (JAAS), and provides a powerful declarative security model for Web resources. WebLogic Server supports three different types of J2EE authentications mechanisms: BASIC, FORM, and CLIENT-CERT. The discussion below assumes a FORM-based authentication scenario but can also apply to other authentication mechanisms.

The key entities that interact in this security model are:

  • A Web resource like a JSP page, which is secured by declarations in the web.xml descriptor file.
  • An authentication provider that creates JAAS subjects and principals during a successful user login. You can use the standard authentication providers bundled with WebLogic Server, such as the LDAP authentication provider, or you can create a custom authentication provider. The authentication provider is configured in the administration console.
  • The WebLogic Security Framework that keeps everything together.
  • HTTP sessions, where an authenticated subject is stored.

This article examines the interplay between these components, and then looks at how you can use an internal WebLogic Server API to capture JAAS events in the event of an HTTP session expiration.

WebLogic Security Framework

Imagine a Web user requests a secured JSP page. If the user is not authenticated, the WebLogic Security Framework redirects the user to a login page. When a user attempts to log onto the Web application, the container calls to the Security Framework, accessing the authentication provider. A successful login results in the creation of a JAAS subject, which contains one or more authenticated principals. This JAAS subject is stored within an internal HTTP session object. Any subsequent requests from the user to a secured resource are authorized by locating the subject from the session.

The flow chart below shows in detail the sequence of events that occur during this process.

Figure x
Figure 1. The sequence of events during the login process (click the image for a full-size screen shot)

What Happens When an HTTP Session Expires?

When an HTTP session expires and the client makes a request to any secured resource, the JAAS subject will not be found for authorization. At this point, the security framework creates a new HTTP session, stores the target URL value in the session, and then redirects the user to the login page. After a successful login process, the user is forwarded back to the target page.

The consequence of this behavior is that the application will never be able to detect that the session expired as it will always have a valid session available.

Some Web applications may need to capture these session expiration events and show some custom message to the user. These may also be required for audit purposes. So how can you make your application aware of these events?

Introducing the weblogic.servlet.security.AuthFilter

The weblogic.servlet.security.AuthFilter abstract class, as part of the WebLogic Server security API, provides hooks into the internal workings of the WebLogic JAAS Framework. It has the following methods that can be overridden by an implementing class:

/** Called just before Authentication and Authorization occurs
                        

 in the Web Application. */
                        

public void  
                         doPreAuth(javax.servlet.ServletRequest req,
                        

 javax.servlet.ServletResponse res)
                        

                         

/** Called just after Authentication and Authorization occurs
                        

 in the Web Application, if the process was a success. */
                        

public boolean  
                         doSuccessAuth(javax.servlet.ServletRequest req,
                        

 javax.servlet.ServletResponse res)
                        

                         

/** Called just after Authentication and Authorization occurs
                        

 in the WebApplication, if the process was a failure. */
                        

public void  
                         doFailAuth(javax.servlet.ServletRequest req,
                        

 javax.servlet.ServletResponse res)
                        


                      

Note that when authentication and authorization fails, the originally requested URL can still be found in the session under the key AuthFilter.TARGET_URL.

To install such a filter, it should be referenced from the weblogic.xml descriptor file, from within the auth-filter tag. Here is an example:

<weblogic-web-app>
                        

 <!-- standard WebLogic settings here -->
                        

 <auth-filter>com.demoapp.util.DemoJAASAuthFilter</auth-filter>
                        

</weblogic-web-app>
                        

 

                      

Capturing Session Expired Attribute

The plan should now be clear. You need to create a class, ApplicationAuthFilter, in this case, that extends weblogic.servlet.security.AuthFilter, and overrides the doPreAuth() method to capture a session expired event and set an attribute in the HTTP session. I use a key defined as Constants.SESSION_EXPIRED. See the following code snippet for such an implementation:

public void doPreAuth(javax.servlet.ServletRequest request, 

                      javax.servlet.ServletResponse response)  {

 // get the session

 HttpSession session = ((HttpServletRequest)request).getSession(false);

 if(session == null) {

   // Create a new session

   session = ((HttpServletRequest)request).getSession(true); 

   //set the session expiration attribute

   if (((HttpServletRequest)request).getRequestedSessionId() != null) {

     session.setAttribute(Constants.SESSION_EXPIRED, "true");

   }

 }

}

Now you can use this Constants.SESSION_EXPIRED attribute in the application to determine if the session expired. Remember to remove this attribute from the session to avoid showing the session expired message repeatedly. See the code snippet below for the Login.jsp:

<%
                        

 if (session.getAttribute(Constants.SESSION_EXPIRED)!=null) {

   out.print("Your session has expired! Please login again!");

   session.removeAttribute(Constants.SESSION_EXPIRED);

 }

%>
                      

You may be wondering, "Why not use an HTTP session listener to capture the session expiration event?" The HTTP session listener does not allow you to create a new session, so you need to store the information that the previous session expired.

Conclusion

Capturing an expired session is just one of the AuthFilter's uses. You may find it useful for other security-related events, depending on your requirements.

The WebLogic Server documentation says that weblogic.servlet.security.AuthFilter has been deprecated in favor of the Servlet Filter specification. But the servlet filter does not provide the same kind of hooks into the internal working of JAAS as discussed above, so you can't capture expired session events with a servlet filter (because when it's called, a valid session already exists). The AuthFilter API is still available in WebLogic 9.0, so it looks like this API will be around for a while yet.

Rajesh Shah