Skip to content
stoffera edited this page Oct 10, 2012 · 3 revisions

Duality supports very fine grained access control. The system consist of methods allowing you to control which user has access to what resource and method to handle login functionality. To get the access control system running to only need 3 things:

  1. Provide you own user table with credentials.
  2. Provide a function that will check if a user (session) has access to a URL.
  3. Provide either a login webpage for form based logins, or use the build-in HTTP Authentication.

The system works by letting you define a set of callback methods. Duality will delegate access control decisions to these callbacks. We will look at creating a HTTP Authentication based system.

##HTTP Authentication Duality support the digest variant of HTTP Auth. This is the secure variant of the HTTP Auth schemes. It is only secure in comparison with the basic HTTP Auth scheme. Be warned that none of these schemes are to be considered secure in relation to the industry standard SSL encryption.

HTTP Auth Digest works by hashing users password. Only the username is transmitted in clear text, the password is a hash, created from: the username, 2 random seeds, a realm and the password itself. The server hashes the same info and matches the two hashes. Note that modern hash cracking systems will likely crack the digest hash in seconds. So do not use this login system with sensitive data.

The Basic HTTP Auth scheme just transfers username and password in clear text. But this scheme is not supported by Duality.

To use HTTP AUth with Duality must must provide at least 3 callback functions:

  • accessResourceCallback
  • httpAuthUserLookupCallback
  • httpAuthLoginSuccessCallback

All callback should be provided as options in the option object passed to the createServer()function.

###accessResourceCallback This callback is called upon every single incoming request. Before any route is followed or any file is served, Duality will query this function to check if the client has access to the resource. The function get called with 3 arguments: the session object, the request and the response objects. Duality expects the function to return true if access is granted and false if not.

Inside this function you check if the client is logged in. You can du this by storing login information in the session object. Let say that logged in client will have a login property in the session, set to true. Then the body of the callback could look like:

        var checkAccess = function(session, req, res) {
	if (session.login && session.login == true) {
		return true;
	}
	else 
		return false;
};

Notice how we first check if the property login exists and then check its value. This function will simple grant any logged in user access to any resource. If you want to limit some users access to certain resources, you must put some user information in the session and parse the URL. You can get the URL from the request object.

###httpAuthUserLookupCallback When a client has filled in the user credentials in the HTTP AUth dialog, the server will need to validate these credentials. It is your job to maintain a table of users. The simple insecure way is to just have a object with username and passwords. In reality you should never ever do that, but for now we do it for learning purpose.

The callback receives 3 arguments: the username and the request and response objects. Then the callback must return a hashed value of the username, realm and password. You do not have to hash the string yourself, you can use the provided method httpAuthHash(). This method will has the username and password properly. Lets see an example of the body of the user lookup callback:

    /* Users table */
    var users = {
        'admin':'secret',
        'guest':'1234'
    };
    
    /* user lookup callback */
    var userLookup = function(username, req, res) {
	if (!users[username]) return null; /* The username does not exist */
	return server.httpAuthHash(username, users[username]); /* return the hash of the username and password */
    };

The callback function will check if the user exists at all. If the user does not exists the function are required to return NULL. If the user do exist, we hash the username and the correct password found in the users table. The hash is returned and the server will check if the user credential were correct or not. It is not up this function to validate is the password was correct, this is done by comparing hashes inside the server.

The helper method httpAuthHash() is defined on the server instance object, which is returned by the createServer function. This method hashes the username and password with the correct realm.

#####The correct way of storing passwords You should not store the clear text passwords of your users. This is highly unethical and insecure. Instead hash the passwords as they are added to the user list. Then just return the hash in the user lookup callback:

    /* Users table */
    var users = {
        'admin':'97e5303d0194c1855ff5a508b3fbb7d4',
        'guest':'0eefbb9d2cce86127cd451c966f40645'
    };
    
    /* user lookup callback */
    var userLookup = function(username, req, res) {
	if (!users[username]) return null; /* The username does not exist */
	return users[username]; /* return the hashed value */
    };

This approach is the way to go. To get the hash values for the users table Duality provide a function that will do this: getHttpAuthUserDigest. This function takes 3 arguments: username, realm and password. The function is defined on the duality module object.

###httpAuthLoginSuccessCallback The last callback to provide for HTTP Auth to work, is to tell us that user authentication succeeded. The callback is called when the 2 hashes from the user credentials matches.

The callback receives 3 arguments: username, request and response. It should not return anything. You should use this callback to setup you user session, so returning request will be logged in as well. The body of the callback could be:

    var loginSuccess = function(username, req, res) {
	req.currentSession.login = true;
    };

Notice this function sets the login property on the session object. This will cause the accessResourceCallback callback to know the user is logged in.

##Form based Authentication Duality provides an optional option where you can specify a URL for the form based page. This URL is called in the access control check fails. It is up to you to manage login routines, log out routines and user tables.

Clone this wiki locally