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.
Appweb implements a powerful and flexible authentication framework that verifies username and password and verifies client capabilities using a role based authorization mechanism.
Appweb 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.
The authentication scheme is selected and controlled by the AuthType appweb configuration directive. This directive may be used inside a Route, VirtualHost block, or default server configuration.
The format of the AuthType directive is:
AuthType auth-scheme realm [scheme-details ...]
<Route /private/> AuthType form example.com AuthStore config User julie 9d8873a123eb506e7f8e84d1f2a26916 administrator administrator teacher Role administrator manage Role teacher supervise teach Require user julie </Route>
This example authenticates access to URLs beginning with "/private" using the Form authentication scheme. It permits access by the user "julie" once authenticated, and uses the "config" password store that defines users via User configuration directives.
The User directive defines a user with an encrypted password and the authorized roles. The Role directive defines role for which users may possess. Roles define a set of capabilities expressed as simple words. Typically, User and Role directives are placed in a separate configuration file, often called auth.conf This file is then typically included from the appweb.conf file via an "include auth.conf" directive.
The Form authentication scheme uses a web page for the user to enter their username and password. These values are then submitted to Appweb via a Http POST request. Appweb analyzes the username 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.
To configure Form authentication, the AuthType directive may take additional arguments to manage the login sequence. The Form variant of AuthType may specify a login web page, a login service URL, a logout service URL, a destination web page once authenticated and a destination page once logged out. The format is:
AuthType form realm Login-Page Login-Service Logout-Service Logged-In-Destination Logged-Out-Destination
This defines the URLs that are invoked during the login sequence and creates special request routes for these URLs. These routes will permit access to the login page and login service so they can be accessed by unauthenticated users. Each of these AuthType arguments is optional and may be specified as the empty string "" to omit. For example:
<Route ^/> AuthType form example.com /public/login.html /login /logout /index.html /public/login.html </Route> <Route ^/public/> Prefix /public Documents public AuthType none </Route>
This example enables Form authentication for all requests and will redirect the client browser to /public/login.html where the user can enter their username and password. The login web page should submit the username and password to the login service bound to the /login URL. When logout is required, the client should submit a HTTP POST request to the logout service bound to the /logout URL. The last two fields in the AuthType directive are the destination URL to which the client's browser will be redirected once logged in and when logged out. The second /public route enables access to documents under the "public" directory without authentication.
The Login-Service is URL that is bound to an internal service to receive the username and password and authenticate the user. This service expects the username/password to be submitted via POST data using the input fields "username" and "password". You can supply your own login and logout service by specifying the empty string "" for the Login-Service in the AuthType directive. If using your own Login Service, you should call httpLogin to validate the user against the configured password store.
Here is a minimal example login page:
<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.
If the login attempt succeeds, the client will receive a response including a session cookie and will be redirected to the Destination URL. If the destination URL includes a referrer: prefix and the login request contained a referrer URL in the HTTP header, then that referrer URL will be used as the destination instead of the hard-wired destination.
SECURITY WARNING: The Form authentication mechanism submits the user password as plain text. To secure communications, the Form authentication scheme should be used over a secure connection using TLS/SSL.
If you are using ESP, Ejscript, PHP or other web framework, you should not use the extended AuthType directive with URLs. This is because these web frameworks have integrated login facilities that are more natural to use within the web framework. The extended AuthType form directive is ideal for web sites using static web pages as it seamlessly manages the browser page transitions during login.
The Require directive controls access to the resources managed by the route. There are three possibilities to control access: require specific named users, require a secure protocol such as TLS/SSL to be used, and require that the authenticated user possess a set of specified abilities.
- Require user username ...
- Require ability name...
- Require secure
When using Require ability, the abilities may be roles defined via the Role directive, abilities specified in Role definitions, or they may be simple words which represent a discrete ability that is explicitly specified with roles in the User directive.
The require secure directive specifies that the SSL/TLS protocol must be used for the request to permit access. The redirect "secure" directive may be used to seamlessly redirect the user's browser to use SSL for the same URL.
Note: These three require directive alternatives may be used in combination. However, multiple Require user or multiple Require ability directives are not supported. The last directive will take precedence.
Appweb provides two samples for user login:
If you are using ESP, please consult the ESP login samples at:
- login-form — ESP Form Authentication Sample
- login-database — ESP Form Authentication with passwords in an application database
Security Concerns and Patterns
While user login may seem like a simple operation, there are hidden complexities. An application that requires secure login must consider:
- The login web page and transmission of username and password credentials must be encrypted with SSL.
- The login web page must contain load only resources over SSL. Mixing the use of HTTP and HTTPS in a single page is flagged by modern browsers as a security risk. This means all required stylesheets, scripts and images must be loaded over SSL.
- The login page and all its required resources must be accessible without prior authentication ‐ after all, it is the login page!
- There may be portions of the application that need to be accessible without authentication and portions that require authentication for access.
- Once logged in, the application may wish to switch back to HTTP for performance if the server is running on a modest embedded CPU.
These requirements may be addressed using a couple of design patterns.
There are two primary options when securing transmission of sensitive information to and from the application :
- Secure the entire application
- Secure only sensitive information including the login page and login service.
Appweb makes it easy to secure the entire application. Simply use the Redirect secure directive. This is suitable for faster systems where the SSL encoding overhead is minimal (less than 5% on a PC class system). But for more modest embedded CPUs, the SSL encryption overhead may be prohibitively large, especially if using large keys.
This will automatically redirect all requests over SSL and may be used for the entire server or for a specific request route only.
The alternative is to secure just the login page, and login/logout services. This can be easily achieved by using https:/// prefix on the AuthType URLs. For example:
AuthType form example.com https:///public/login.html https:///login /logout http:///index.html
This will create the required routes and automatically switch to SSL for the login.html page and when sending credentials to /login. It will automatically switch back to HTTP once logged in.
To secure other portions of the application, define a route that redirects securely. For example:
<Route ^/sensitive/> Prefix /sensitive Documents top-secret Redirect secure </Route>
Make sure that all absolute URLs referenced from the login page use https and not http. Mixing the loading of resources from http and https will lead to warnings from client browsers
What to Authenticate?
There are often portions of the application that may be accessed without authentication and other portions that require authentication. For example: The login page and login service must be exempt from authentication. To do this, define a publicroute and disable authentication via an AuthType none directive. For example:
<Route ^/public/> Prefix /public Documents public AuthType none </Route>
This will create a route where all URLs prefixed with "/public" will be unauthenticated. Then if the login page is stored under public it will be accessible before logging in.
An alternative approach is to require authentication only for server-side URLs and to enable unauthenticated access to all static web content as "public".
See the HttpAuth API for APIs to manage authentication and authorization under program control. See also the mprMakePassword and mprCheckPassword APIs to create and check Blowfish encrypted passwords.
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
Appweb Basic authentication is enabled by the AuthType basic configuration directive.
<Route /private/> AuthType basic example.com User julie 9d8873a123eb506e7f8e84d1f2a26916 view </Route>
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.
Digest authentication is enabled the AuthType digest directive.
<Route /private/> AuthType Digest example.com include auth.conf </Route>
Appweb can access passwords from configuration file directives or from the system password database. Selection of the password store is controlled by the AuthStore directive. For example:
This selects the Unix system password database. Note: the Windows ActiveDirectory password store is not currently supported.
The supported Auth Stores are:
- app — Application (custom) Password Database
- config — Configuration Directives
- system — System Password Database
The authpass program creates user passwords that may be used for the config or app AuthStores. If using an application defined database store, the AuthStore should be set to "app" and the passwords created by authpass should be stored in your application database.
The authpass program will create passwords and may be used to modify User directives in an authentication file.
The command line syntax for authpass is:
authpass [--cipher blowfish|md5] [--file auth.conf] [--password word] realm username roles...
The --file filename option specifies the name of the authentication file, if unspecified, the password will be printed on the standard output. The --cipher option specifies the cipher used to hash/crypt the password. The default is MD5 which is required for digest authentication, however blowfish is more secure. Blowfish is preferable for Basic and Form authentication schemes. If the --password option is not used, authpass will prompt for the password. The realm defines a group of passwords and is set via the AuthType directive. It is typically set to a company domain or product name.
The authpass program can modify password definitions in a configuration file. Here is a sample authentication configuration file that contains User and Role directives.
SECURITY WARNING: it is essential that the authentication file be stored outside the Documents directory or any directory serving content.