User Authentication

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 controls client capabilities using a role based authorization mechanism.

There are two components to the Appweb authentication architecture.

Authentication Password Stores

Appweb can access passwords from one of three password stores:

The supported Auth Stores are:

The "app" store is where passwords are stored by the user application in a database or other custom password store. It is the responsibility of the user application to implement a credential verification callback that will be invoked by Appweb to access the custom password store and compare supplied supplied credentials with the user password. This store is ideal when you need the ability to modify users and passwords at runtime.

The "config" store manages passwords in the Appweb configuration file via "User" directives. Passwords are created via the "authpass" program and defined in the appweb.conf configuration file. This store is suitable if you do not need to dynamically add, remove or modify users or passwords.

The "system" store manages passwords using the system (e.g. /etc/password) password database.

The selection of the password store is controlled by the AuthStore directive. For example:

AuthStore system

This selects the Unix system password database. Note: the Windows ActiveDirectory password store is not currently supported.

Verifying Passwords

If using the "app" store, you will need to register a callback that will be used to verify user credentials. Use the httpSetAuthStoreVerifyByName API to register your verification callback for all routes using the store. Alternatively, use the httpSetAuthVerify API to define the callback for just one route using the store.

Creating Passwords

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 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 authpass program can also modify password definitions in a configuration file.

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.

SECURITY WARNING: it is essential that the authentication file be stored outside the Documents directory or any directory serving content.

Authentication Protocols

Authentication protocols define how the user credentials are captured from the user and supplied to Appweb. Appweb provides several authentication protocol schemes.

Application Authentication

Application authentication uses application specific means to capture the user name and password. The user application is responsible for implementing the control logic to capture user credentials and redirect the client through the login and logout process. This protocol is best used for applications that utilize server-side web frameworks such as ESP.

Form Authentication

The form authentication scheme uses a HTML web form for the user to enter their username and password credentials and a HTTP Post request to submit credentials to the server for verification. With this protocol, you define specific login and logout pages and via the AuthType directive. Appweb manages the login/logout process and if authentication succeeds, a login session is created and a cookie is returned to the client's browser. Subsequent requests that include the cookie will be automatically authenticated and served.

To configure form authentication, the AuthType directive requires additional arguments to manage the login sequence. These specify a login web page, a login service URL, a logout service URL, a destination web page that is displayed 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 directive defines the URLs that are used during the login sequence. The directive creates request routes as required for these URLs that will permit access to the login page and login service 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 / /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.

Web Form

Here is a sample 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 for use by the "form" authentication scheme.

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.

Basic and Digest Authentication

The Basic and Digest authentication are HTTP protocol mechanisms defined by the HTTP/1.1 RFC2616 specification. Because they operate at the HTTP 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.

SECURITY NOTE

You should only use Basic and Digest authentication as a last resort. Basic and Digest authentication standards employ weak ciphers, repeatedly send credentials over the wire and and are not sufficiently secure. Basic authentication transmits passwords as clear-text in each and every request. Digest authentication uses the weak MD5 cipher, and both require use of SSL on all requests to be minimally secure. Further, both Basic and Digest do not provide a reliable log out mechanism. Logout works on some browsers but not on others or even different versions of the same browser. We strongly recommend using "form" authentication, with "blowfish" encryption for a more usable, secure and reliable solution.

Configuring Authentication

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 ...]

For example:

<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.

Web Frameworks

If you are using ESP, PHP or other web framework, you should not use the extended "AuthType form" 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. When using the ESP web framework, use the "AuthType app" authentication protocol by choice.

Require Directive

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.

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.

Samples

Appweb provides two samples for user login:

If you are using ESP, please consult the ESP login samples at:

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:

These requirements may be addressed using a couple of design patterns.

SSL Encryption

There are two primary options when securing transmission of sensitive information to and from the application :

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.

Redirect secure

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:///

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".

Authentication APIs

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

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>

Digest Authentication

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>

© Embedthis Software. All rights reserved.