Richard G Baldwin (512) 223-4758, baldwin@austin.cc.tx.us, http://www2.austin.cc.tx.us/baldwin/

Security, Servlets, Using Basic Authentication

Java Programming, Lecture Notes # 705, Revised 5/13/99.


Preface

Students in Prof. Baldwin's Advanced Java Programming classes at ACC will be responsible for knowing and understanding all of the material in this lesson beginning with the spring semester of 1999.

This lesson was originally written on March 28, 1999.

The sample servlet in this lesson was tested using Win95, Netscape Navigator, the JDK 1.2 download package from JavaSoft, the JSDK 2.0 download package from JavaSoft, and the Jigsaw web server that, as of 3/27/99, was freely available from http://www.w3.org/Jigsaw/. The sample program was tested using Jigsaw from the same machine, and also from a different machine on the network.

Disclaimer

I claim absolutely no expertise in the area of security. I am simply a college professor attempting to gather information about Java on one hand and present it to my students on the other. I disclaim any responsibility for any security problems that may occur as a result of anyone using any of the material in any of my tutorial lessons.

You are responsible for your own actions. With regard to security, you should study not only the material that I will present, but also material provided by others who possess expertise in the security area. Hopefully my material will be useful in getting you started in that direction.

Two good books on security published by O'Reilly & Associates are:

I highly recommend both of these books.

Introduction

Much of the material in this lesson is a repeat of the material in a previous lesson on session tracking, but with a different slant.

What is Basic Authentication?

Most HTTP servers provide a very weak form of security commonly known as Basic Authentication.

An HTTP server that provides Basic Authentication has the capability to maintain a list of user names and passwords.

It also has the capability to protect resources (directories, files, servlets, etc.) making those resources available only to specified users.

How is this information maintained?

The manner in which the list of user names and passwords is maintained, and the manner in which resources are protected, differs from one server to the next.

For the sample program in this lesson, I used the administrator features of the Jigsaw server to establish the list and the protection. You will need to see your server documentation for more information on this topic.

What does it mean for a resource to be protected?

When a resource is protected and a client attempts to access it, the server requires the client to provide the user's name and password.

Typically, the browser obtains the name and password from the user and provides it to the server. If that user is authorized to access the requested resource, the request is granted.

What happens next?

Thereafter, the browser remembers and resends the name and the password as the user views different pages on the same site. This continues until the user moves on to a different site or exits the browser.

If the user comes back to the site before exiting the browser, the process of sending the name and password resumes.

How does this involve servlets?

After the user logs in to the server by providing the name and password to the browser, the user name is available to the servlet through the getRemoteUser() method.

Assuming that the user name is unique, it can be used as a key to persistent storage (such as a database) for the purpose of maintaining information about the session.

Problems with Basic Authentication

An earlier lesson suggested that during network communications, you should be concerned with

Basic Authentication provides no support for Confidentiality and Integrity. It does provide a very weak form of Authentication.

So, what is the problem?

The main problem with the Authentication model provided by Basic Authentication is the ease with which someone else can decode the user name and password information if they can intercept it.

This is illustrated by the sample program later in this lesson where a method of one of the Sun classes is used to decode and display the user name and password.

A site that relies on Basic Authentication cannot be considered secure.

However, in some cases where the value of the material that might be compromised is low, the site administrator may be more interested in ease of use than security and the use of Basic Authentication might be appropriate.

Digest Authentication

Some server/browser combinations support a more secure form of authentication known as Digest Authentication. Rather than sending the user name and password in the simple encoded form mentioned above, it is encrypted using a secure encryption algorithm. A dialog is conducted between the server and the browser that makes it possible for the two to exchange the encrypted information.

I mention this here only to alert you to the fact that it may provide you with a secure alternative to Basic Authentication. If you know that Digest Authentication is supported both by your server and by all of the browsers that will be used by your clients, you may want to consider its use.

Sample Program

The name of the servlet discussed below is Servlet13A. This is one of a group of three similar servlets named:

What was protected?

In my case, the server was set up to protect all three servlets by protecting the directory in which they are stored. (It is also possible to protect individual servlets and individual files.)

The list of users having access to the servlets in the protected directory was set up to include the user named dick.

What happens next?

When the client makes a request to invoke one of the servlets, the server requires the client to provide a name and password.

The server compares the name and password to the list of valid name/password combinations maintained in the database by the server. If the name/password combination is not valid, the client gets another opportunity to provide a name and password.

If the name/password combination is valid, the server compares the name to the list of names established as having access to the directory containing the servlet.

If the name matches one of the names on that list, the servlet is invoked on behalf of the client.

What does the servlet do?

When one of the servlets is invoked, it produces an output similar to the following on the client screen (only the name of the servlet differs from one servlet to the next):

Welcome to Servlet13A 
Hello dick
Authentication Type: Basic
Authorization: Basic ZGljazpkcm93c3NhcA==
Unencoded name and password: dick:drowssap
Please visit these other servlets:
Servlet13A
Servlet13B
Servlet13C

The encoded name and password

The fourth line shows the simple encoded version of the name and password passed over the Internet as:.

Authorization: Basic ZGljazpkcm93c3NhcA==

Decoded name and password

The fifth line shows the user name and password after it has been decoded by the servlet as:

Unencoded name and password: dick:drowssap

As mentioned earlier, the ease with which this information can be decoded causes this to be an extremely weak security model.

The remaining output

The last three lines in the output are hyperlinks to each of the three servlets.

Having invoked any one of the three servlets, the user can again invoke any one of the three. No matter which one is invoked, the servlet is able to identify the user and to get the user's name and password.

Interesting Code Fragments

The first fragment shows the beginning of the controlling class and the beginning of the doGet() method.

The fragment also shows the typical HTML boilerplate necessary to create an HTML page to be sent to the client. You have seen material such as this many times before.

public class Servlet13A extends HttpServlet{
  public void doGet(HttpServletRequest req, 
                    HttpServletResponse res)
                      throws ServletException, IOException{
    res.setContentType("text/html");
    PrintWriter out = res.getWriter();
    out.println("<HTML>");
    out.println("<HEAD><TITLE=Servlet13A</TITLE></HEAD>");
    out.println("<BODY>");
    
    out.println("Welcome to Servlet13A <BR>");

The getRemoteUser() method

The next fragment uses the getRemoteUser() method to get and display the name of the remote user. Note that the user name is available without performing any special decoding of the incoming information.

    out.println("Hello " + req.getRemoteUser() + "<BR>");

Once the user has logged in, this name is available to servlets on this server until the user exits the browser. Therefore, it is important for the user to exit the browser when the session has been completed.

The getAuthType() method

The next fragment gets and displays the type of authentication being used by the server.

    out.println("Authentication Type: " 
                             + req.getAuthType() + "<BR>");

In this case, the type is Basic Authentication.

As mentioned earlier, some servers also support a more secure form of authentication known as Digest Authentication.

The getHeader() method

The next fragment shows the use of the getHeader() method to get and display the authorization string in its encoded format.

    String auth = req.getHeader("Authorization");
    out.println("Authorization: " + auth + "<BR>");

Note that the string "Authorization" is passed to the method in order to get the authorization string.

Recall from above that the value of the authorization string displayed was:

Basic ZGljazpkcm93c3NhcA==

The boldface portion of this string contains the encoded version of the user name and password.

No single method available...

There is no single method available for extracting the password as is the case with the name, but the password isn't difficult to extract.

The next fragment

    String encodedNamePassword = auth.substring(6);
    sun.misc.BASE64Decoder dec = 
                              new sun.misc.BASE64Decoder();
    String unencodedNamePassword = 
         new String(dec.decodeBuffer(encodedNamePassword));
    out.println("Unencoded name and password: " 
                         + unencodedNamePassword + "<BR>");

In my case, the unencoded version is displayed as

dick:drowssap

Anybody can do it

Any computer that can intercept the communication between the client and the server can decode the user name and password just as easily.

The remaining code

The remaining code (not shown here) creates hyperlinks for all three of the servlets allowing the user to navigate among the different servlets at will. Each time the user invokes any one of these servlets prior to exiting the browser, the name and password information for that user will be available as shown above.

The remaining code also provides the boilerplate necessary to close out the HTML page. You can view the remaining code in the next section.

Program Listing

A complete listing of one of the servlets follows. The other two servlets are identical to this one with the exception of the servlet name, so they aren't shown here.

/*File Servlet13A.java, Copyright 1999, R.G.Baldwin
Rev 3/25/99
This is one of a group of three servlets:
Servlet13A
Servlet13B
Servlet13C

that are designed to illustrate session tracking using 
BASIC AUTHENTICATION.

All three servlets are protected by the server.  When the
user requests the server to invoke one of the servlets,
the server requires the user to provide a name and 
password.  That name and password is compared, by the
server, to the set of name/password combinations maintained
in a database by the server.

If the name/password combination is valid, the server
compares the name to the list of names established by
the server administrator as being allowed access to the
servlet.  If the name matches one of the names on that
list, the servlet is invoked on behalf of the client.

When the servlet is invoked, it produces an output
similar to the following on the client screen:
  
Welcome to Servlet13A 
Hello dick
Authentication Type: Basic
Authorization: Basic ZGljazpkcm93c3NhcA==
Unencoded name and password: dick:drowssap
Please visit these other servlets:
Servlet13A
Servlet13B
Servlet13C

where the last three lines are hyperlinks to each of the
three servlets.

The servlet was tested using the JDK 1.2 download package
from JavaSoft along with the Java Servlet Development Kit
(JSDK) 2.0 from JavaSoft and the Jigsaw web server. All 
tests were performed under Win95.

**********************************************************/
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class Servlet13A extends HttpServlet{
  public void doGet(HttpServletRequest req, 
                    HttpServletResponse res)
                      throws ServletException, IOException{
    res.setContentType("text/html");
    PrintWriter out = res.getWriter();
    out.println("<HTML>");
    out.println("<HEAD><TITLE=Servlet13A</TITLE></HEAD>");
    out.println("<BODY>");
    
    out.println("Welcome to Servlet13A <BR>");

    out.println("Hello " + req.getRemoteUser() + "<BR>");
    out.println("Authentication Type: " 
                             + req.getAuthType() + "<BR>");
    String auth = req.getHeader("Authorization");
    out.println("Authorization: " + auth + "<BR>");
    String encodedNamePassword = auth.substring(6);
    sun.misc.BASE64Decoder dec = 
                              new sun.misc.BASE64Decoder();
    String unencodedNamePassword = 
         new String(dec.decodeBuffer(encodedNamePassword));
    out.println("Unencoded name and password: " 
                         + unencodedNamePassword + "<BR>");
    out.println("Please visit these other servlets:<BR>");

    out.println("<A HREF=\"http://baldwin:8001/servlets"
                + "/Servlet13A\">Servlet13A</A>" + "<BR>");
    out.println("<A HREF=\"http://baldwin:8001/servlets"
                + "/Servlet13B\">Servlet13B</A>" + "<BR>");
    out.println("<A HREF=\"http://baldwin:8001/servlets"
                + "/Servlet13C\">Servlet13C</A>" + "<BR>");


    out.println("</font></h1>");
    out.println("</BODY></HTML>");
  }//end doGet()
}//end class Servlet13A

-end-