HTTP Authentication in Node.js
Last week, in Creating a HTTP Server in Node.js, I covered the basics of HTTP in Node.js. Today’s article will show you how to password protect your Node.js site using HTTP authentication. We’ll start by looking at basic access authentication, and then move on to the more secure digest access authentication.
Basic Access Authentication
When a user visits a site that implements authentication, he/she is prompted for a username and password. If the user provides valid credentials they are taken to the page’s content, otherwise they are rejected with a “401 Unauthorized” response. The simplest type of HTTP authentication is basic access authentication.
The Password File
On the server side, all of the usernames and encrypted passwords are stored in a password file. The Node.js utility, htpasswd
can be used to manage the password file. To install htpasswd
, use the command shown below. npm
stands for Node.js Package Manager, and it is installed by default with Node.js. npm
is used to install Node.js modules. The -g
flag installs the package globally, meaning that it is included in the system’s PATH
variable.
npm install -g htpasswd
Once htpasswd
is installed, you can create new users using the command shown below. This example creates a new password file named “htpasswd” using the -c
flag. In the new file, a user named “foo” is added. The -b
flag allows the password, “bar”, to be specified as part of the command line.
htpasswd -bc htpasswd foo bar
After running the command, open your “htpasswd” file. The password file entry for the user “foo” is shown below. This line contains the username and encrypted password. Since this is the first and only user in the file, this should be the only line in the file.
foo:{SHA}Ys23Ag/5IOWqZCw9QGaVDdHwH00=
Node.js Incorporation
The next step is to add authentication support to our HTTP server. First, you will need to install the http-auth
module using the following npm
command.
npm install http-auth
Next, create a new file named “basic_auth_server.js”, and add the code shown below. Notice that the http-auth
module is referenced on line 2. On lines 3 through 7, a configuration object is passed to the authentication module. The authRealm
field defines an authentication realm. The authFile
field points to the password file we created earlier. __dirname
refers to the directory that the currently executing script resides in. This example assumes that the “htpasswd” file is in the same directory as “basic_auth_server.js”. The authType
configuration field indicates the type of authentication to use. On line 9, the basic authentication scheme is applied to the HTTP connection. The authentication callback function provides the authenticated username for further processing.
var http = require("http");
var auth = require("http-auth");
var basic = auth({
authRealm: "Private area",
authFile: __dirname + "/htpasswd",
authType: "basic"
});
var server = http.createServer(function(request, response) {
basic.apply(request, response, function(username) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello " + username);
response.end();
});
});
server.listen(80);
console.log("Server is listening");
Finally, start the server. You can connect to the server by navigating to http://localhost
. You will be prompted for a username and password. Provide the credentials you created earlier, and the browser will respond by greeting you by name.
Limitations
The biggest shortcoming of basic access authentication is the fact that credentials are sent over the network as plaintext. This type of authentication should only be used with secure (i.e. HTTPS) connections in order to prevent eavesdropping. If a secure connection is not available, a more secure form of authentication should be used instead.
Digest Access Authentication
Digest access authentication is a more secure alternative to basic authentication. With digest authentication, passwords are encrypted prior to network transmission.
The Password File
Digest authentication also uses a password file. However, the format of the file is slightly different from the one used for basic authentication. In order to work with the digest password file format, we will use a different utility named htdigest
. Install htdigest
using the following npm
command.
npm install -g htdigest
Next, create a new password file using the command shown below. Again, the -c
flag is used to create a new password file named “htpasswd”. This time we must also specify an authentication realm. In this case, the authentication realm is “Private area”. In this example, the username is “foo” again. Notice that the password is not provided in the command. Once you enter the command, you will be prompted to provide the password.
htdigest -c htpasswd "Private area" foo
After running htdigest
, look inside the new “htpasswd” file. The entry for “foo” is shown below. The digest authentication file contains the username and encrypted password, as well as the authentication realm, which was not included in the basic authentication file.
foo:Private area:b8e1b1c08abcd38173a7dba3ad93a0c3
Node.js Incorporation
To incorporate digest authentication into our server, we will use the http-auth
module again. If you’ve been following along with this tutorial, the module should already be installed on your machine. Next, create a new file named “digest_auth_server.js” to implement your server. The server code is shown below. Notice that the server code is nearly identical to the basic authentication server code. The difference lies in the authType
field of the configuration object. In this case, authType
has been set to "digest"
. This server can be accessed in the same fashion as the basic authentication server.
var http = require("http");
var auth = require("http-auth");
var digest = auth({
authRealm: "Private area",
authFile: __dirname + "/htpasswd",
authType: "digest"
});
var server = http.createServer(function(request, response) {
digest.apply(request, response, function(username) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello " + username);
response.end();
});
});
server.listen(80);
console.log("Server is listening");
Conclusion
This article has covered the basics of HTTP authentication. By following the examples provided here, your Node.js applications can be a little more secure. However, you should be aware that authentication alone is not enough. If security is a primary concern, your site should be served over HTTPS. In future articles, I’ll explore HTTPS and many other awesome Node.js features.
If you’ve enjoyed this post, you’re going to want to learn all about SitePoint’s newest series of print and ebooks, Jump Start. The first title is Node.js by Don Nguyen — find out more at SitePoint!