Authentication is the process by which a client's identity and capabilities are verified before granting access to server resources. Authentication is essential when you have content that you wish to protect and provide only to specific, approved clients.
GoAhead implements a powerful and flexible authentication framework that verifies username and password and verifies client capabilities using a role based authorization mechanism.
GoAhead provides several authentication protocol schemes.
The Form authentication scheme uses a HTML web form for the user to enter their username and password credentials and HTTP Post requests to submit to the server for verification. It may also be used programmatically va HTTP POST requests.
The Basic and Digest authentication are HTTP protocol mechanisms defined by the HTTP/1.1 RFC2616 specification. Because they operate at the protocol level, they offer a lower level of capability and flexibility. When a client attempts to access secured content, the client's browser displays a generic pop-up dialog box to prompt for the user's credentials.
Authentication is controlled by two configuration files:
- auth.txt — which contains authorization directives
- route.txt — which contains URI routing directives
Together these two files define the authentication scheme to be used for each and every request to GoAhead. When GoAhead is run, the auth.txt and route.txt file are read and authenticated routes are created for each specified URI pattern. When client requests are received, they are matched against the URI routes to find the required authentication scheme. This enables great flexibility as different requests can use different authentication schemes.
The auth.txt file contains user and role definitions to establish an authentication database. If running on a Unix system, the standard Unix user database may be used instead of defining users in auth.txt.
Users can be defined via the user directive. This specifies the username, encrypted password and the authentication roles played by the user.
Roles can be defined via the role directive. This specifies the role name and a set of ability words. URI routes may require that a user has certain abilities before access is granted.
role name=manager abilities=view,edit,delete user name=joshua password=2fd6e47ff9bb70c0465fd2f5c8e5305e roles=manager
The route.txt file contains route definitions that specify how each request URI will be processed and what, if any, kind of authentication will be required for the request. For example:
route uri=/private/ auth=digest abilities=edit route uri=/cgi-bin handler=cgi
The auth keyword takes an argument set to digest, basic or form. The abilities keyword takes a comma separated list of ability words.
The Form authentication scheme uses a standard web page form that prompts for the user to enter their name and password. This scheme allows the user login interface to have the same look and feel as the rest of the web application.
The Form authentication scheme submits the username and password to GoAhead via a standard Http POST request. GoAhead analyzes the user and password, and if authenticated, a login session is created and a cookie is returned to the users's browser. Subsequent requests that include the cookie will be automatically authenticated and served. Because the username and password are sent in the clear, it is important that Form authentication only be used over SSL connections.
The form authentication scheme is enabled via the auth=digest keyword on required routes. For example:
route uri=/ auth=form handler=continue redirect=401@/login.html
Secure Form-based Authentication
To effectively secure an application using Form authentication requires five routes to implement the login and logout process. These are:
- Route to redirect all HTTP traffic over SSL
- Route for the login page which must be accessible when unauthenticated
- Route for the login service
- Route for the logout service
- Route to require authentication for all URIs
route uri=/ protocol=http redirect=*@https handler=redirect route uri=/pub/ route uri=/action/login methods=POST handler=action redirect=200@/ redirect=401@/pub/login.html route uri=/action/logout methods=POST handler=action redirect=200@/pub/login.html route uri=/ auth=form handler=continue redirect=401@/pub/login.html
Redirect over SSL
route uri=/ protocol=http redirect=*@https handler=redirect
This directive is responsible for redirecting all HTTP traffic over SSL. The uri=/ defines a URI prefix. Since all URIs start with /, this route will match all requests that use http:// and not https://.
Unauthenticated Access to the Login Page
The Login Service
route uri=/action/login methods=POST handler=action redirect=200@/ redirect=401@/pub/login.html
This directive defines the login service route. The action handler bind the login service to the URI /action/login. This service expects a POST request with username and password form fields. If the user authenticates, the user is redirected via redirect=200@/. The redirection form is: STATUS@URI. If the user credentials cannot be authenticated successfully, the user is redirected back to the login page via: redirect=401@/pub/login.html.
The Logout Service
route uri=/action/logout methods=POST handler=action redirect=200@/pub/login.html
This directive defines the logout service. This simply deletes the user's login session and redirects the user back to the login page.
route uri=/ auth=form handler=continue redirect=401@/pub/login.html
This final directive defines a route that matches all other URIs and stipulates form-based authentication. The continue handler authenticates the user and if the user is successfully authenticated, processing continues on to let other handlers service the request and generate a response. If authentication fails, the user is redirected back to the login page.
Here is a minimal example login form:
<html><head><title>login.html</title></head> <body> <p>Please log in</p> <form name="details" method="post" action="/auth/login"> Username <input type="text" name="username" value=''><br/> Password <input type="password" name="password" value=''><br/> <input type="submit" name="submit" value="OK"> </form> </body> </html>
The two submitted fields must be named username and password.
Securing the Password
SECURITY WARNING: The Form authentication scheme submits the user password as plain text. To secure communications, the Form authentication scheme should be used over a secure connection using TLS/SSL.
Basic authentication was the original HTTP/1.0 authentication scheme. It captures usernames and passwords via a fixed browser-based popup dialog and then transmits credentials using a trivial encoding that is no better than using plain text.
SECURITY WARNING: You should not use Basic Authentication if at all possible. It transmits user credentials with each request, has no encryption for the password and does not have a means for users to reliably logout. If you must use Basic Authentication, use it over TLS/SSL which will encrypt the password over the wire.
Basic Authentication Directives
GoAhead basic authorization is defined by specifying auth=basic in the required routes in route.txt. For example:
# In auth.txt role name=operator abilities=start,stop user name=julie password=9d8873a123eb506e7f8e84d1f2a26916 roles=operator # In route.txt route uri=/machinery auth=basic abilities=start,stop
This example restricts access to URIs beginning with "/machinery". It permits access to the users with the start, stop abilities. This means that the user "julie" will be granted access once authenticated.
The auth=basickeyword specifies that basic authorization is being used. The Authentication Realm used by Basic and Digest authentication is set when GoAhead is built via the realm property in the main.me configuration file. The realm is used in combination with the username and password to encrypt the password.
The Digest authentication scheme cryptographic techniques is a minor improvement over the Basic scheme. It captures usernames and passwords via a fixed browser-based popup dialog and then transmits credentials using the weak MD5 encoding format.
SECURITY WARNING: You should not use Digest Authentication if at all possible. It transmits user credentials with each request, has weak encryption for the password and does not have a means for users to reliably logout. If you must use Digest Authentication, use it over TLS/SSL which will securely encrypt the credentials over the wire.
GoAhead digest authorization is very similar to Basic authentication and is is controlled by the auth=digest keyword on required routes.
GoAhead can be built to retrieve passwords from the Unix system password database or from password text configuration file. The Unix system password database is managed via the PAM interface. GoAhead can be configured to use PAM with the command:
configure --set pam=true
Determining Abilities with PAM
When using PAM, user records are not required in auth.txt. However, to determine the users's abilities, the Unix group membership for the user and role definitions are used. For each Unix group that the user is a member of, a corresponding role in auth.txt is checked. If a role of the same name as the group exists, the abilities specified by that role are added to the set of abilities for the user. In other words, you should create a role definition for each group in auth.txt that will specify the abilities for users in that Unix group. For example, say a user joshua was a member of the Unix group "staff". The following auth.txt definitions would give joshua the abilities: add,edit,delete.
Role staff add,edit,delete
To create the required encrypted password fields for user definitions, the gopass program is used. It can generate passwords and edit the auth.txt with updated user definitions. The command line syntax for gopass is:
gopass [--cipher cipher] [--file path] [--password password] realm user roles...
The file parameter specifies the name of the authentication file which is typically "auth.txt". If the --file option is omitted, the calculated hash for the password will be displayed to the console. If the --password option is omitted, gopass will prompt for the password. The realm is the name specified by the realm property in the main.me configuration file when GoAhead was built. It defaults to: "example.com". You may set this to any string you like. If you are using Basic or Digest authentication, this string will be displayed at the top of the login popup dialog. If using Form authentication, it is never displayed to the user and is only used to salt the encryption of the passwords.
The gopass program supports the MD5 and Blowfish ciphers. MD5 must be used if you are using digest authentication. If using a web-based authentication scheme, it is strongly advised that you use the blowfish cipher as it is much more resistant to cracking the password hashes.
SECURITY WARNING: it is essential that the authentication file be stored outside the DocumentRoot or any directory serving content.