HOWTO: Configure basic Authentication on Jetty using a Hash Login Service

When operating a webserver it may be useful to have a simple mechanism to protect particular web contents against public access, for example to create a member's area within a website, containing information which is accessible by members only, and require user/password authentication to be read or downloaded. Most web hosters run Apache webservers and thus provide the well known htaccess/htpassword mechanism for that purpose. That mechanism basicly works by placing text files named .htaccess, in which access information to the folder and it's subfolders or to particular files is placed, in folders of the site's webspace. Each .htaccess file contains a reference to a list of user/password credentials stored in a file named .password, which is usually placed in some central administration folder of the site's webspace.
That mechanism, however, is specific to the most popular Apache webserver. Jetty provides a similar mechanism, which is little more complex, but still quite simple. Unfortunately it is not well documented, so here's a brief introduction to get started.

The following example is based on Jetty 9.3.6, an instance of which is running on a Debian or Ubuntu driven computer.

Configure a Realm in Jetty

A realm can be viewed as a part of the webserver-accessible file system, which can be affected by the specified authentification mechanism. If Jetty s installed on /opt/jetty, this is, by default, everything underneath /opt/jetty/webapps. In this HOWTO, we regard this default only, skipping more sophisticated realm definition options provided by Jetty.

To configure a realm in Jetty, create the following entry in the jetty.xml file:

   vi /opt/jetty/etc/jetty.xml

This indicates to Jetty, that a HashLoginService-based realm named Default Realm, sourcing credentials from a hash table stored in plain text file /opt/jetty/etc/, is established. Jetty provides more LoginService types other than HashLoginService, which are not covered by this HOWTO.

The name Default Realm is referred to by the web pages/services to which we want to add authentication. You might modify the name according to your requirements.

The file does not yet exist and needs to be created manually in /opt/jetty/etc. It will contain user/password/role information for every user. You might also modify name and position of that file, keeping the respective jetty.xml entry up-to-date. We're leaving it as is here and will now have a look on the contents of the file. Here's an example:
   vi /opt/jetty/etc/
   guest: guest11,user-role
   jim: MD5:d45e977bfef260da159d651b9de7035d,user-role
There are two users, guest and jim, registered in the file. guest has the plain password "guest11", while jim has the MD5-coded Password "zigzag". Both users bear the role user-role. While user guest's password is written in plain text, user jim has his password coded into a MD5 string. Note that MD5: needs to be the password prefix in There are plenty of sources in the web to create the MD5 sum representation of a (password) string, but you can also use the Unix command line:
   echo -n "zigzag" | md5sum
   d45e977bfef260da159d651b9de7035d  -
So, the general format of a user entry in a realm porperty file is
   <user>: <password-string>,<role>
   where <user>
            is a username, followed by a : and a whitespace character,
            is the user's password, either as plain text or coded as MD5, SHA, OBFuscated or CRYPTed 
            string with their respective prefixes MD5:, SHA:, OBF: or CRYPT: 
              ( no blank between : and the password string ) 
     and <role>
            is an identifier to distinguish users with different access according to their roles, 
            e.g. user-role, admin-role, ...
For more user options, check the Jetty documentation. Credentials can be added, changed or removed in the realm property file as needed.
That's all to configure in Jetty for BASIC authentication using a HashLoginService, unless advanced authentication functionality is required.

Use authentication in Web pages and Web applications

A little unlike Apache, Jetty focusses more on Web applications or Web services than on Web pages, but this is not really a restriction. In Jetty, all published contents is located under the webapps folder. Typically, a web application is in a subfolder underneath the webapps folder and contains executable code in (Java) class files as well as an administrative sub structure, which - amoung other stuff - in particular includes an additional subfolder named WEB-INF, and that WEB-INF subfolder contains a deployment descriptor XML file named web.xml. Alternatively, the same Web application structure can be packed in a .war archive file, which is placed directly in the webapps folder instead of an application subfolder.
"Ordinary" (HTML-based) Web pages are treated just like Web applications, so for a particular Web site there is a subfolder underneath webapps, containing the pages, downloads and other contents. For example, if Jetty is running on the localhost and a Web site is placed in a subfolder named samplesite underneath the webapps folder, the site's index.html home page can be browsed by opening the http://localhost/samplesite URL.

Here's a (simplified) example structure of the contents published on a Jetty Web server:
              +-- README.TXT
              +-- root
               +-- index.html
              +-- samplewebservice1
               +-- servicehome.class
               +-- servicetool.class
               +-- WEB-INF
                   +-- web.xml
              +-- samplewebservice2.war
              +-- samplewebservice3.war			  
              +-- samplesite
                  +-- index.html
Now, in comparison to Apache, the file can be regarded as the Jetty counterpart to the .htpasswd file. And within the sammplewebservice1 web application in the above example, the counterpart of the Apache .htaccess file would be a section of the WEB-INF/web.xml file from the Jetty perspective. Before having a closer look into WEB-INF/web.xml, let's turn to the example once more. Web applications like samplewebservice1, samplewebservice2 and samplewebservice3 always need and include a WEB-INF/web.xml file. This is immediately visible for samplewebservice1, but also the samplewebservice2.war and samplewebservice3.war WARs both contain a WEB-INF/web.xml file. However "standalone" HTML sites like samplesite do not contain a WEB-INF/web.xml file by default, because Jetty doesn't need it to just serve HTML pages. So, if authentication is to be established for HTML pages, the WEB-INF/web.xml needs to be created explicitly within the samplesite folder, and the file structure of the site will then look like this:
              . . .
              +-- samplesite
                  +-- index.html
                  +-- WEB-INF
                     +-- web.xml
              . . .			  
Now, let's have a look into a sample web.xml file:

This is quite simple. The only information about the servlet is it's display name and it's home page(s) (welcome files), so we can assume that all other relevant deployment information is hard coded in the servlet's source code. So far, no authentication is set in the web.xml file, so let's tell the web service to be available to users with role user-roll only, by authentication. Therefore we just add the following code to the "web-app" section of web.xml:

With this, the samplewebservice2 servlet requires authentication by any user having role user-role assigned in /opt/jetty/etc/, which is the property file for realm Default Realm as defined in /opt/jetty/etc/jetty.xml.

Authentication is required for the complete servlet, i.e from it's deployment (root) folder ( packed in /opt/jetty/webapps/samplewebservice2.war ) downwards, as is denoted by the /* url-pattern tag.

In practise, for example, a POST service method, provided by the servlet, could be invoked by a web browser, where data is entered in a HTML form to be sent to the service. The service would then process the data and send a confirming response back to the client (i.e. the browser finally shows a page, displaying the information that the data was successfully processed). With authentication as configured here, a user/password authentication dialog, provided by Jetty, would appear as the user clicks on the Submit button of the form. The service would only be executed after the user entered a correct username/password combination for a user with role user-role, as defined in the file.

In an ordinary web site, which consists of informational contents mainly (or only), usually HTML pages, rather than service applications, authentication is established the same way. Just add WEB-INF/web.xml under the web site's root folder ( e.g. /opt/jetty/webapps/samplesite ) and fill the web.xml file with suitable contents, for example:

Let's assume, that this web.xml file is part of a web site which consists of an index.html page in the site's root folder, which - next to WEB-INF contains another two subfolders named public and protected. Pages contained in all those folders may be linked to each other.
   +-- index.html
   +-- protected
    +-- protected_document.html
   +-- public
    +-- public_document.html
   +-- WEB-INF
       +-- web.xml
Now, the
line in security-constraint / web-resource-collection section of the web.xml file indicates that all contents (files) in the protected subfolder requires authentication, whereas the root folder, including index.html as well as all the contents of the public subfolder are public and can be accessed without authentication.
So, on localhost, if you browse the site's index.html home page using the http://localhost/samplesite URL, you're likely to find a link to ./protected/protected_document.html, and on selecting that link, an authentication dialog will appear and ask for username and password before granting access to protected_document.html .

Once Jetty is configured and a WEB-INF/web.xml file is available on the web site or application path, maintenance is done by entering or editing user data in the file and protecting folders and files in the web.xml file on demand.

Documentations on