Feature: Using User Authentication

                       There are two ways of restricting access to documents: either by the hostname of the
                       browser being used, or by asking for a username and password. The former can be used to,
                       for example, restrict documents to use within a company. However if the people who are
                       allowed to access the documents are widely dispersed, or the server administrator needs to
                       be able to control access on an individual basis, it is possible to require a username and
                       password before being allowed access to a document. This is called user authentication.

                       Setting up user authentication takes two steps: firstly, you create a file containing the
                       usernames and passwords. Secondly, you tell the server what resources are to be protected
                       and which users are allowed (after entering a valid password) to access them.

                       Creating a User Database

                       A list of users and passwords needs to be created in a file. For security reasons, this file
                       should not be under the document root. The examples here will assume you want to use a file
                       call users in your server root at /usr/local/etc/httpd.

                       The file will consist of a list of usernames and a password for each. The format is similar to
                       the standard Unix password file, with the username and password being separated by a
                       colon. However you cannot just type in the usernames and passwords because the
                       passwords are stored in an encrypted format. The program htpasswd is used to add create a
                       user file and to add or modify users.

                       htpasswd is a C program that is supplied in the support directory of the Apache distribution. If
                       it is not already compiled, you will to compile it first. Run

                         make htpasswd

                       in the support directory to compile it (you might need to modify the Makefile first, since any
                       configuration you did when compiling the server itself is not available to this makefile). After
                       compilation, you can either leave the htpasswd binary where it is, or move it to a directory on
                       your path (e.g. /usr/local/bin). In the former case, you will need to remember to give the full
                       pathname to run it. The examples here will assume that it is installed somewhere on your
                       path.

                       Using htpasswd

                       To create a new user file and add the username "martin" with the password "hampster" to the
                       file /usr/local/etc/httpd/users:

                          htpasswd -c /usr/local/etc/httpd/users martin

                       The -c argument tells htpasswd to create new users file. When you run this command, you
                       will be prompted to enter a password for martin, and confirm it by entering it again. Other
                       users can be added to the existing file in the same way, except that the -c argument is not
                       needed. The same command can also be used to modify the password of an existing user.

                       After adding a few users, the /usr/local/etc/httpd/users file might look like this:

                       martin:WrU808BHQai36
                       jane:iABCQFQs40E8M
                       art:FAdHN3W753sSU

                       The first field is the username, and the second field is the encrypted password.

                       Configuring the Server

                       To get the server to use the usernames and passwords in this file, you need to configure a
                       realm. This is a section of your site that is to be restricted to some or all of the users listed
                       in this file. This is typically done on a per-directory basis, with a directory (and all its
                       subdirectories) being protected (Apache 1.2. will let you protect individual files). The directives
                       to create the protected area can be placed in a .htaccess file in the directory concerned, or in
                       a <Directory> section in the access.conf file.

                       To allow a directory to be restricted within a .htaccess file, you first need to ensure that the
                       access.conf file allows user authentication to be setup in a .htaccess file. This is controlled
                       by the AuthConfig override. The access.conf file should include AllowOverride AuthConfig to
                       allow the authentication directives to be used in a .htaccess file.

                       To restrict a directory to any user listed in the users file just created, you should create a
                       .htaccess file containing:

                         AuthName "restricted stuff"
                         AuthType Basic
                         AuthUserFile /usr/local/etc/httpd/users

                         require valid-user

                       The first directive, AuthName, specifies a realm name for this protection. Once a user has
                       entered a valid username and password, any other resources within the same realm name
                       can be accessed with the same username and password. This can be used to create two
                       areas which share the same username and password.

                       The AuthType directive tells the server what protocol is to be used for authentication. At the
                       moment, Basic is the only method available. However a new method, Digest, is about to be
                       standardised, and once browsers start to implement it, digest authentication will provide more
                       security than the basic authentication.

                       AuthUserFile tells the server the location of the user file created by htpasswd. A similar
                       directive, AuthGroupFile, can be used to tell the server the location of a groups file (see
                       below).

                       These four directives have between them tell the server where to find the usernames and
                       passwords and what authentication protocol to use. The server now knows that this resource
                       is restricted to valid users. The final stage is to tell the server which usernames from the file
                       are valid for particular access methods. This is done with the require directive. In this
                       example, the argument valid-user tells the server that any username in the users file can be
                       used. But it could be configured to allow only certain users in:

                         require user martin jane

                       would only allow users martin and jane access (after they entered a correct password). If user
                       art (or any other user) tried to access this directory - even with the correct password - they
                       would be denied. This is useful to restrict different areas of your server to different people with
                       the same users file. If a user is allowed to access the different areas, they only have to
                       remember a single password. Note that if the realm name differs in the different areas, the
                       user will have to re-enter their password.

                       Using Groups

                       If you want to allow only selected users from the users file in to a particular area, you can list
                       all the allowed usernames on the require line. However this means you are building username
                       information into your .htaccess files, and might not been convenient if there are a lot of users,
                       and . Fortunately there is a way round this, using a group file. This operates in a similar way
                       to standard Unix groups: any particular user can be a member of any number of groups. You
                       can then use the require line to restrict users to one or more particular groups. For example,
                       you could create a group called staff containing users who are allowed to access internal
                       pages. To restrict access to just users in the staff group, you would use

                         require group staff

                       Multiple groups can be listed, and require user can also be given, in which case any user in
                       any of the listed groups, or any user listed explicitly, can access the resource. For example

                         require group staff admin
                         require user adminuser

                       which would allow any user in group staff or group admin, or the user adminuser, to access
                       this resource after entering a valid password.

                       A group file consists of lines giving a group name followed by a space-separated list of users
                       in that group. For example:

                         staff:martin jane
                         admin:art adminuser

                       The AuthGroupFile directive is used to tell the server the location of the group file. Note that
                       the maximum line length within the group file in about 8000 characters (actually 8kB). If you
                       have more users in a group than will fit within that line length, you can have more than one
                       line with the same group name within the file.

                       Problems with Large Numbers of Users

                       Using htpasswd to create a text list of users, and maintaining a list of groups in a plain text
                       file is relatively easy. However if the number of users becomes large, the server has a lot of
                       processing to do to find a user's group and password details. This processing has to be done
                       for every request inside the protected area (even though the user only enters their password
                       once, the server has to re-authenticate them on every request). This can be slow with a lot of
                       users, and adds to the server load. Much faster access is possible using DBM format files.
                       This allows the server to do a very quick lookup of names, without having to read through a
                       large text file. However managing DBM files is more complex. Apache Week will cover the
                       use of DBM authentication in a future issue.

                       Other Ways of Storing User Details

                       While Apache by default can only access user details in plain text files, various add-on
                       modules are available to allow user details to be stored in databases. Besides DBM format
                       (available with the mod_auth_dbm module), user and group lists can be stored in DB format
                       files (with mod_auth_db). Or full databases can be used, such as mSQL (with
                       mod_auth_msql), Postgres95 (mod_auth_pg95) or any DBI-compatible database
                       (mod_auth_dbi).

                       It is also possible to have an arbitrary external program check whether the given username
                       and password is valid (this could be used to write an interface to check against any other
                       database or authentication service). Modules are also available to check against the system
                       password file, or to use a Kerberos system. See the feature on Adding Modules for more
                       information.

                       Limiting Methods Differently

                       In the example .htaccess file above, the require directory is not given inside a <Limit>
                       section. This is valid in Apache, and means it applies to all request methods. In other servers
                       and most example .htaccess files, the require directive is given inside a <Limit> section, such
                       as this:

                         <Limit GET POST PUT>
                         require valid-user
                         </Limit>

                       In Apache it is better to omit the <Limit> and </Limit> lines, to ensure that the protection
                       applies to all methods. However, this format can be used to limit particular methods. For
                       example, to limit just the POST method, use

                         AuthName "restrict posting"
                         AuthType Basic
                         AuthUserFile /usr/local/etc/httpd/users

                         <Limit POST>
                         require group staff
                         <Limit>

                       Now only members of the group staff will be allowed to POST. Other users (unauthenticated)
                       can use other methods, such as GET. This could be used to allow a CGI program to be
                       accessed by anyone, but only authorised uses can POST information to it.

                       Restricting By Hostname or Username

                       One feature of the NCSA server is that is allows a request to be allowed if it comes from
                       within a particular domain name, or if not, to ask for a valid username and password (using
                       the satisfy directive). This is a combination of restricting by username and by the user's
                       hostname. Unfortunately Apache currently cannot do this.

                       How WWW Authentication Works

                       The method used in HTTP for user authetication is quite simple. Since HTTP is a stateless
                       protocol - that is, the server does not remember any information about a request once it has
                       finished - the browser needs to resend the username and password on each request. Here is
                       how it works.

                       On the first access to an authenticated resource, the server will return a 401 status
                       ("Unauthorized") and include a WWW-Authenticate response header. This will contain the
                       authentication scheme to use (at the moment, only Basic is allowed) and the realm name.
                       The browser should then ask the user to enter a username and password. It then requests the
                       same resource again, this time including a Authorization header which contains the scheme
                       name ("Basic") and the username and password entered.

                       The server checks the username and password, and if they are valid, returns the page. If the
                       password is not valid for that user, or the user is not allowed access because they are not
                       listed on a require user line or in a suitable group, the server returns a 401 status as before.
                       The browser can then ask the user to retry their username and password.

                       Assuming the username and password was valid, the user might next request another
                       resource which is protected. In this case, the server would respond with a 401 status, and the
                       browser could send the request again with the user and password details. However this would
                       be slow, so instead the browser sends the Authorization header on subsequent requests.
                       Note that the browser must ensure that it only sends the username and password to further
                       requests on the same server (it would be insecure to send those details if the user moved
                       onto a different server).

                       The browser needs to remember the username and password entered, so it can send them
                       with future requests from the same server. Note that this can cause problems when testing
                       authentication, since the browser remembers the first username and password that works. It
                       can be difficult to force the browser to ask for a new username and password.