Sunday, August 1, 2010

Declarative Container Managed Authentication

Motivation

For web applications that provide dynamic content tailored to individual users, authentication is an important concern. Authentication confirms that a user is, indeed, who they claim to be. As a result, (web) applications employ authentication to confirm the identities of users and protect privileged resources.

The Java Servlet specification supports declarative authentication, which eases the implementation of a web application's authentication strategy. By using declarative authentication, web developers simply declare that some or all of the application's resources are protected. Web developers are liberated from the burden of writing code that describes how those security constraints are enforced.

This tutorial provides a quick overview for web developers who want to take advantage of the Servlet specification's support of declarative authentication. The tutorial covers both container-agnostic elements of the web.xml file that support declarative authentication, as well as some authentication-related features of the Tomcat servlet container.

Securing Web Resources Declaratively

The web.xml file is the first stop on the way to adding declarative authentication to a web application. In that file, we'll want to declare what type of authentication should be used. By appropriately configuring a <login-config> element, we can tell the servlet container what query method should be used when authenticating users. Several options are available, though form-based authentication is the most common.

<login-config>
  <auth-method>FORM</auth-method>
  <form-login-config>
    <form-login-page>
      /WEB-INF/pages/login.jsp?info=login
    </form-login-page>
    <form-error-page>
      /WEB-INF/pages/login.jsp?info=login_failed
    </form-error-page>
  </form-login-config>
</login-config>

The <login-config> element above tells the servlet container how it should authenticate users for the related web application. Next we need to tell the servlet container which resources in the web application require that the user be authenticated.

<security-constraint>
  <web-resource-collection>
    <web-resource-name>Secured Resources</web-resource-name>
    <description>
      Only logged in users should be able to visit the 
      resources in this collection.
    </description>
    <url-pattern>/command/*</url-pattern>
  </web-resource-collection>
  <auth-constraint>
    <role-name>user</role-name>
  </auth-constraint>
  <user-data-constraint>
    <transport-guarantee>NONE</transport-guarantee>
  </user-data-constraint>
</security-constraint>

<security-role>
    <role-name>user</role-name>
</security-role>

The <security-constraint> element above provides a trivial example in which all URLs that map to the pattern "/command/*" are secured so that they may only be accessed by authenticated users in the "user" role.

Defining a JDBCRealm

All of the authentication-related configuration that we did above in the web.xml file is highly portable since that file will be packaged and deployed with our web application. Notice, however, that the configuration work we did in web.xml isn't sufficient by itself to support declarative authentication. Specifically, we've not yet told the Servlet container where and how to access the web application's list of valid users with related passwords.

This is where we have to delve into some container-specific details. By default, the Tomcat servlet container will attempt to authenticate by reading the user names and passwords defined in its $CATALINA_HOME/conf/tomcat-users.xml file. Obviously, this is not very convenient if we intend to use a relational database to store information about our web application's users.

Thankfully, it's easy to configure Tomcat to read from a relational database instead of the tomcat-users.xml file when authenticating users. To do so, we'll need to configure a new Realm, which is Tomcat's generic term for a collection of information about users.

<Realm 
    className="org.apache.catalina.realm.JDBCRealm"
    driverName="org.postgresql.Driver"
    connectionURL="jdbc:postgresql://localhost:5432/YourDatabaseName"
    connectionName="your_db_username" 
    connectionPassword="your_db_password"
    userTable="user_table_name" 
    userNameCol="user_name_column_name" 
    userCredCol="user_password_column_name"
    userRoleTable="uesr_role_table_name" 
    roleNameCol="role_name_column_name" />

The <Realm> element defined above tells Tomcat how it can use a relational database to authenticate users.

Configuring Web Application Context

In the section above we saw how to define a <Realm> element that instructs Tomcat to employ our relational database when authenticating users. One final consideration remains: where should we place that <Realm> definition? A single Tomcat server can host multiple web applications. Presumably each of those web applications may want to use a different database to authenticate its users. As a result, we should locate our <Realm> element within the <Context> element for our web application so that the Realm applies only to our web application.

A good way to include a <Realm> element within the web application's <Context> is to include a META-INF/context.xml file in our web application. By defining a <Realm> element within such a file, we can ensure that the application will use the appropriate relational database for authentication, regardless of which Tomcat server it is deployed to.

Granting Security Privileges

One final, useful note is that we may need to augment the security constraints for our application server if we want it to use an external relational database for user authentication. For the Tomcat Servlet container, we can add an entry to the $CATALINA_HOME/config/catalina.policy file.

grant {
    permission java.net.SocketPermission "localhost:5432", 
    "connect,resolve";
};    

The above statement grants permission for any class in the servlet container to lookup and connect to our database, which runs on the localhost at port 5432.

No comments:

Post a Comment