Tuesday, November 23, 2010

Glassfish JDBCRealm authentication against DSpace user database

A project we're working on at the library requires a DSpace repository webapp to cooperate with a custom data-submission webapp that we're building. We want our custom webapp to authenticate with the same credentials that dspace manages in its internal database. Luckily, our glassfish app-server includes a JDBC security realm that fit this problem perfectly.

It took me several hours of head banging and googling ( http://blogs.sun.com/swchan/entry/jdbcrealm_in_glassfish_with_mysql , http://blogs.sun.com/swchan/entry/jdbcrealm_in_glassfish , http://blogs.sun.com/swchan/entry/assign_groups , http://stackoverflow.com/questions/719708/java-web-application-using-a-custom-realm ) to figure out all the steps to properly configure a glassfish JDBCRealm to authenticate our webapp. I was really glad it worked in the end. I configured a glassfish JDBC security realms with the following properties to access the 'email' and 'password' column's in the dspace 'eperson' database table. The following data in domain.xml can be configured via the glassfish admin webapp

    <jdbc-connection-pool
datasource-classname="org.postgresql.ds.PGSimpleDataSource"
is-isolation-level-guaranteed="false" res-type="javax.sql.DataSource"
description="connection to local dspace database" name="dspace">
      <property name="DatabaseName" value="dspace" />
      <property name="LogLevel" value="0" />
      <property name="LoginTimeout" value="0" />
      <property name="Password" value="XXXXX" />
      <property name="PortNumber" value="0" />
      <property name="PrepareThreshold" value="5" />
      <property name="ProtocolVersion" value="0" />
      <property name="ServerName" value="localhost" />
      <property name="SocketTimeout" value="0" />
      <property name="Ssl" value="false" />
      <property name="TcpKeepAlive" value="false" />
      <property name="UnknownLength" value="2147483647" />
      <property name="User" value="XXXXX" />
    </jdbc-connection-pool>
 
    <jdbc-resource pool-name="dspace" description="dspace data source"
jndi-name="jdbc/dspace" />
 
        <auth-realm
classname="com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm"
name="dspaceRealm">
          <property name="datasource-jndi" value="jdbc/dspace" />
          <property name="jaas-context" value="jdbcRealm" />
          <property name="user-table" value="eperson" />
          <property name="user-name-column" value="email" />
          <property name="password-column" value="password" />
          <property name="group-table" value="epersongroup" />
          <property name="group-name-column" value="name" />
          <property name="assign-groups" value="users" />
        </auth-realm>
 

Finally, we configure our webapp to use the dspaceRealm with the following blocks in WEB-INF/web.xml:

 
    <!--
       Login config for production server.
       See role-mapping in sun-web.xml too.
       Details of dspaceRealm configuration for glassfish in bLog.
 
    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>dspaceRealm</realm-name>
    </login-config>
    <security-role>
        <role-name>users</role-name>
    </security-role>
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Secure Pages</web-resource-name>
            <url-pattern>/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>users</role-name>
        </auth-constraint>
    </security-constraint>
   -->

... and WEB-INF/sun-web.xml:

    <!-- Enable on production server - see note in web.xml ....
    <security-role-mapping>
        <role-name>users</role-name>
        <group-name>users</group-name>
    </security-role-mapping>
    -->

In the end I wanted to send an e-mail to the dspace tech-list, but I was disappointed to discover that there is not a standard way to incorporate JAAS authentication into an application server security realm. All the app servers have a slightly different way of implementing security realms, and the setup I describe above is glassfish specific, but that's good enough for me for now.