The Basic Authentication standard has been in place since the 1990s and can be the simplest way to provide a user login. When used over HTTP, it is in no way secure since a plain text password is sent over the connection from browser to server.
For information on Basic Authentication see http://en.wikipedia.org/wiki/Basic_authentication.
However, when coupled with SSL (HTTPS), Basic Authentication can be a useful method if we're not concerned about a custom-styled login form.
We discuss SSL/TLS (HTTPS) in the Setting up an HTTPS web server recipe of this chapter. For extra information see http://en.wikipedia.org/wiki/SSL/TLS.
In this recipe, we'll learn how to initiate and process a Basic Access Authentication request over plain HTTP. In following recipes, we'll implement an HTTPS server, and see an advancement of Basic Authentication (Digest Authentication).
Basic Authentication specifies a username, password, and realm, and it works over HTTP. So we'll require the HTTP module, and set up some variables:
var http = require('http'), var username = 'dave', password = 'ILikeBrie_33', realm = "Node Cookbook";
Now we'll set up our HTTP server:
http.createServer(function (req, res) { var auth, login; if (!req.headers.authorization) { authenticate(res); return; } //extract base64 encoded username:password string from client auth = req.headers.authorization.replace(/^Basic /, ''), //decode base64 to utf8 auth = (new Buffer(auth, 'base64').toString('utf8')); login = auth.split(':'), //[0] is username [1] is password if (login[0] === username && login[1] === password) { res.end('Someone likes soft cheese!'), return; } authenticate(res); }).listen(8080);
Notice we make two calls to a function named authenticate
. We need to create this function, placing it above our createServer
call:
function authenticate(res) { res.writeHead(401, {'WWW-Authenticate' : 'Basic realm="' + realm + '"'}); res.end('Authorization required.'), }
When we navigate to localhost:8080
in our browser we are asked to provide a username and password for the Node Cookbook
realm. If we provide the correct details, our passion for soft cheese is revealed.
Basic Authentication works via a series of headers sent between server and browser. When a browser hits the server, the WWW-Authenticate
header is sent to the browser and the browser responds by opening a dialog for the user to login.
The browser's login dialog blocks any further content from being loaded in the browser until the user either cancels or attempts to log in. If the user presses the Cancel button, they see the Authorization required message sent with res.end
in the authenticate
function.
However, if the user attempts to log in, the browser sends another request to the server. This time it contains an Authorization
header in response to the WWW-Authenticate
header. We check for its existence at the top of the createServer
callback with req.headers.authorization
. If the header exists, we skip the call to authenticate
and go on to verify the user credentials. The Authorization
header looks like this:
Authorization: Basic ZGF2ZTpJTGlrZUJyaWVfMzM=
The text following Basic
is a Base64-encoded string that holds the username and password separated by a colon, so the decoded Base64 text is:
dave:ILikeBrie_33
In our createServer
callback, we decode the Base64 header by first stripping the Basic
portion from it, load it into a buffer which converts Base64 to binary, then run toString
on the result converting it to a UTF8 string.
See http://en.wikipedia.org/wiki/Base64 and http://en.wikipedia.org/wiki/Comparison_of_Unicode_encodings for information on Base64 and string encodings like UTF-8.
Finally, we split
the login details with a colon, and if the provided username and password match our stored credentials, the user is granted access to authorized content.
Basic Authentication comes bundled with the Express framework as middleware.
Express (via Connect) provides the basicAuth
middleware, which implements this pattern for us. To implement the same in Express:
var express = require('express'), var username = 'dave', password = 'ILikeBrie_33', realm = "Node Cookbook"; var app = express.createServer(); app.use(express.basicAuth(function (user, pass) { return username === user && password === pass; }, realm)); app.get('/:route?', function (req, res) { res.end('Somebody likes soft cheese!'), }); app.listen(8080);
If we now head to http://localhost:8080
, our Express server will behave in the same way as our main recipe.
SeeChapter 6, Accelerating Development with Express, for information on using Express to develop web solutions.
3.134.118.95