Configuring Basic or Digest Authentication for Tomcat-based WebDAV Server

Basic/Digest Authentication 

Important! Microsoft Office on Windows and Mac OS X as well as Windows Shell (Web Folders / mini-redirector), requires secure SSL connection when used with Basic authentication. Microsoft Office will fail to open a document via insecure connection with Basic authentication. For a workaround please see the following articles. In case of MS Office Windows: You cannot open Office file types directly from a server that only supports Basic Authentication over a non-SSL connection with Office applications. In case of MS Office on OS X: You cannot open Office for Mac files directly from a server that supports only Basic authentication over a non-SSL connection.

To configure Basic or Digest authentication using Tomcat preconfigured users/roles:

  1. Configure roles that will have access to webdav repository in /WEB-INF/web.xml file using <security-constraint> element (under <web-app> element):
    <web-app ... > 
       ... 
       <security-constraint>
          <!-- web resources that are protected -->
          <web-resource-collection>
             <web-resource-name>All Resources</web-resource-name>
             <url-pattern>/*</url-pattern>
             <!-- All methods but OPTIONS must be authenticated. OPTIONS must work without authentication for cross domain in Firefox to work -->
             <http-method>GETLIB</http-method>
             <http-method>COPY</http-method>
             <http-method>MOVE</http-method>
             <http-method>DELETE</http-method>
             <http-method>PROPFIND</http-method>
             <http-method>GET</http-method>
             <http-method>HEAD</http-method>
             <http-method>PUT</http-method>
             <http-method>MKCOL</http-method>
             <http-method>PROPPATCH</http-method>
             <http-method>LOCK</http-method>
             <http-method>UNLOCK</http-method>
             <http-method>VERSION-CONTROL</http-method>
             <http-method>CHECKIN</http-method>
             <http-method>CHECKOUT</http-method>
             <http-method>UNCHECKOUT</http-method>
             <http-method>REPORT</http-method>
             <http-method>UPDATE</http-method>
             <http-method>CANCELUPLOAD</http-method>
          </web-resource-collection>
          <auth-constraint>
              <!-- role-name indicates roles that are allowed to access the web resource specified above -->
              <role-name>administrators</role-name>
              <role-name>role1</role-name>
          </auth-constraint>
       </security-constraint> 
       ...
    </web-app>
  2. Configure roles:
    <web-app ... > 
            ... 
            <security-role>
                  <role-name>administrators</role-name>
                  <role-name>role1</role-name>
            </security-role>
            ... 
    </web-app>
  3.  Configure authentication:
    • For Basic authentication add following element after <security-constraint> element:
      <web-app ... > 
          ... 
          <login-config>
              <auth-method>BASIC</auth-method>
              <realm-name>Basic Authentication</realm-name>
         </login-config> 
         ...
      </web-app>
    • For Digest authentication add following element:
      <web-app ... > 
            ... 
           <login-config> 
               <auth-method>DIGEST</auth-method>  
               <realm-name>Digest Authentication</realm-name>  
           </login-config>
              ... 
      </web-app>
  4. Configure users, their names, passwords and roles they belong to in <TOMCAT_HOME>/conf/tomcat-users.xml:
    <tomcat-users>
        <role rolename="manager"/>
        <role rolename="admin"/>
        <role rolename="administrators"/>
        <user username="admin" password="admin" roles="admin,manager"/>
        <user username="sergey" password="sergey" roles="administrators"/>
    </tomcat-users>

In your code, you will be able to access logged in user using request.isUserInRole method:

public List<HierarchyItemImpl> getChildren() throws ServerException {
       if (this.getEngine().getRequest().isUserInRole("administrators")){
              // list items 
       }
       else{
              throw new ServerException(WebDavStatus.ACCESS_DENIED);
       }
}

Authentication Against Custom Users Storage with Tomcat

To authenticate against your credential store using Basic or Digest authentication you need to:

  1. Implement Tomcat custom realm:
    import java.security.Principal; 
    import org.apache.catalina.realm.RealmBase;
    
    public class CustomRealm extends RealmBase { 
         public boolean hasRole(Principal principal, String role) { 
               //determine if principal is in role
         }  
       
         protected String getPassword(String username) { 
              // return password of user with name = 'username' 
         } 
       
         protected Principal getPrincipal(String username) { 
              return new CustomPrincipal(username); 
         } 
       
       class CustomPrincipal implements Principal { 
           private final String name;
           public CustomPrincipal(String name) { 
                this.name = name; 
           }
     
           public String getName() { 
              return name; 
           }
     
           public String toString() { 
              return getName(); 
           } 
       } 
     }
  2. Configure Tomcat to use Custom Realm in <TOMCAT_HOME>/conf/server.xml
    <Server ...>
        ...
        <!-- Because this Realm is here, an instance will be shared globally 
             <Realm className="org.apache.catalina.realm.MemoryRealm" /> -->
        <Realm className="CustomRealm"/>
        ...
    </Server>