Adding your own Authenticator for Restricting Access


Overview

By default, we use Tomcat container-managed security which handles authentication and authorization using standard HTTP mechanisms. You can use your own Authentication by implementing thredds.servlet.restrict.Authorizer and plugging it into the RestrictedDataset servlet in the TDS web.xml.

We have tested this with the following systems:

  1. CAS Single Sign On (SSO) 3.0.6 server. The CAS/Yale 2.1.1 client code ships with thredds.war, and we have an example configuration that you can try. To add a CAS server, just drop the cas.war file into ${tomcat_home}/webapps. Or you may want to run it on a seperate, publically accessible, server.
  2. CAMS server 2.1.33 and their Tomcat servlet filter 2.1.13. CAMS is a commercial SSO provider.

You should follow the steps to get default restricted datasets working, then follow the steps below to plug in your own code.

Configuring web.xml

After thredds.war is expanded, edit ${tomcat_home}/webapps/thredds/WEB-INF/web.xml.

Find the RestrictedDataset servlet element. Comment out the default servlet and substitute yours. As an example, here is the version that uses CAS for authorization (just below the default):

<!-- Restricted Access (using CAS) -->
<servlet>
1) <servlet-name>RestrictedDataset</servlet-name>
<servlet-class>thredds.servlet.restrict.RestrictedDatasetServlet</servlet-class>
2) <init-param>
    <param-name>Authorizer</param-name>
    <param-value>thredds.servlet.restrict.CASAuthorizer</param-value>
   </init-param>
3) <init-param>
      <param-name>RoleSource</param-name>
      <param-value>cisl.tds.restrict.RoleSource</param-value>
    </init-param>

4) <init-param>
    <param-name>RoleDatabase</param-name>
    <param-value>C:/Program Files (x86)/Apache Software Foundation/apache-tomcat-5.5.20/conf/tomcat-users.xml</param-value>
   </init-param>
5) <init-param>
    <param-name>edu.yale.its.tp.cas.client.filter.loginUrl</param-name>
    <param-value>https://localhost:8443/cas/login</param-value>
   </init-param>
   <init-param>
     <param-name>edu.yale.its.tp.cas.client.filter.validateUrl</param-name>
     <param-value>https://localhost:8443/cas/proxyValidate</param-value>
   </init-param>
   <init-param>
     <param-name>edu.yale.its.tp.cas.client.filter.serverName</param-name>
     <param-value>localhost:8080</param-value>
   </init-param>
6) <load-on-startup>2</load-on-startup>
</servlet>
  1. The RestrictedDataset servlet, implemented by thredds.servlet.restrict.RestrictedDatasetServlet
  2. This is where you plug in your own Authorizer class, which implements thredds.servlet.restrict.Authorizer (see below).
  3. You may plug in your own implementation of thredds.servlet.restrict.RoleSource, by naming the class here. (see below).
  4. A special kind of RoleSource is a RoleDatabase XML file (see below). Use a RoleSource or RoleDatabase (not both).
  5. These are any parameters needed to initialize your code. This example has actual parameters used by the CAS 2.1 code.
  6. Loading on startup ensures that any errors are immediately seen, otherwise, the servlet is not loaded until first accessed.

The thredds.servlet.restrict.Authorizer interface

You must implement this interface:

public interface Authorizer {

public void init(HttpServlet servlet) throws ServletException; public void setRoleSource( thredds.servlet.restrict.RoleSource roleSource);
public boolean authorize(HttpServletRequest req, HttpServletResponse res, String role) throws IOException, ServletException;
  public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException;
}

1. The init method allows you to initialize your Authorizer with the servlet parameters, for example:

 public void init(HttpServlet servlet) throws ServletException {
   casLogin = servlet.getInitParameter( "edu.yale.its.tp.cas.client.filter.loginUrl");
   casValidate = servlet.getInitParameter( "edu.yale.its.tp.cas.client.filter.validateUrl");

   ...

2. If you have multiple sets of datasets to restrict, access to each set is controlled by a role, and users are assigned to one or more roles. This is called role-based authentication. You may pass in your own implemention of thredds.servlet.restrict.RoleSource, and your Authorizer is responsible for using it correctly, by calling RoleSource.hasRole( String username, String role) at the appropriate places.

You can also piggyback on the existing thredds.servlet.restrict.RoleDatabase implementation of RoleSource, which reads an XML file that describes the users and roles. You specify the name of the XML file in the web.xml. In the above example, we are using the tomcat-users.xml file, however you can create your own if you prefer. We use only the user elements, and only the username and roles attribute (not the password). For example a minimal file would look like:

<?xml version='1.0' encoding='utf-8'?>
<root> <user username="ccsmData" roles="ccsmData, restrictedDatasetUser"/> <user username="fieldProject" roles="fieldProject, restrictedDatasetUser"/> <user username="tiggeData" roles="tiggeData, restrictedDatasetUser"/> </root>

where the root element can be named anything. If you have only one set of datasets to restrict, you dont need role-based authentication. Then authorization would depend only (in this example) on being authorized by CAS. If you are using CAS and role-based authentication, you must use the same username in the RoleDatabase as in the CAS authorization.

3. The main routine that you must implement is Authorizer.authorize(HttpServletRequest req, HttpServletResponse res, String role). It is called when a restricted dataset is being accessed. Typically when the user has not established credentials, you do a redirect and return false. Return true if the user authenticates properly. See thredds.servlet.restrict.CASAuthorizer as an example.

4. You can optionally use the thredds.servlet.restrict.RestrictedDatasetServlet to do some of the work, by implementing this method. See thredds.servlet.restrict.TomcatAuthorizer as an example. Make it a no-op method otherwise.

You should add your code to the exploded thredds ${tomcat_home}/webapps/thredds/WEB-INF/lib as a jar file, or to the ${tomcat_home}/webapps/thredds/WEB-INF/lib/classes directory as class files. Remember that these directories are overwritten when you upgrade to a new verssion of the thredds.war file.


Notes on using CAMS

1. We assume you already have a CAMS server running. Follow the directions to install the Cams Servlet Filter Web Agent (not the Cams Tomcat 5 Web Agent, which does not work with Tomcat 5.5).

2. Add the CAMS servlet filter to ${tomcat_home}/webapps/thredds/WEB-INF/web.xml. This example uses version 2.1.13:

 <filter>
<filter-name>Cams</filter-name>
<filter-class>com.cafesoft.security.webagent.servletFilter.CamsServletFilterWebAgent</filter-class>
  <init-param>
   <param-name>configPath</param-name>
1) <param-value>C:/Program Files (x86)/Apache Software Foundation/apache-tomcat-5.5.20/conf/cams-webagent.conf</param-value>
  </init-param>
  <init-param>
   <param-name>contextClass</param-name>
   <param-value>com.cafesoft.security.common.agent.StandardCamsAgentContext</param-value>
  </init-param>
 </filter>
 <filter-mapping>
   <filter-name>Cams</filter-name>
2) <url-pattern>/restrictedAccess/*</url-pattern>
 </filter-mapping>
  1. This must be an absolute path to the cams-webagent.conf file.
  2. All URLS of the form /restrictedAccess/* are intercepted by the CAMS filter.

3. Also in web.xml, use the CAMSAuthorizer in RestrictedDatasetServlet:

<!-- Restricted Access (using container managed security, eg Tomcat, or CAMS) -->
<servlet>
<servlet-name>RestrictedDataset</servlet-name>
<servlet-class>thredds.servlet.restrict.RestrictedDatasetServlet</servlet-class>
  <init-param>
   <param-name>Authorizer</param-name>
   <param-value>thredds.servlet.restrict.CAMSAuthorizer</param-value>
  </init-param>
  <load-on-startup>2</load-on-startup>
 </servlet> 

and comment out the default security constraint on /restrictedAccess/* :

  <!-- default restricted access uses DIGEST, but not HTTPS -->
<security-constraint>
<web-resource-collection>
<web-resource-name>restricted access datasets</web-resource-name>
<url-pattern>/restrictedAccess/*</url-pattern>
<http-method>GET</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>restrictedDatasetUser</role-name>
</auth-constraint>
</security-constraint>


Notes on using Jetty and Shibboleth (Pauline Mak)

I've managed to install THREDDS with Jetty, Apache and Shibboleth. If anyone is interested, I have some documentation here:

  http://projects.arcs.org.au/trac/systems/wiki/DataServices/OPeNDAP-TDS-Install  


Notes on ESG and TDS Security

https://wiki.ucar.edu/display/esgcet/Adding+ESG+security+to+a+TDS+server

 

THREDDS This document is maintained by Unidata and was last updated April 2010. Send comments to THREDDS support.