I am reading a book about NodeJs Connect. There is this small part about basicAuth
module. I know that basicAuth
is now deprecated, but I cannot understand this simple code. The book says
Providing an asynchronous callback function
The final option is similar, except this time a callback is passed to basicAuth() with three arguments defined, which enables the use of asynchronous lookups. This is useful when authenticating from a file on disk, or when querying from a database.
Listing 7.7. A Connect basicAuth middleware component doing asynchronous lookups
And no other information. Thats the whole part about having a callback in the basicAuth
So, code gets the username and the password. Then hypothetical object User
has a method authendicate
that checks if this user actually exists. And when its finished, calls the gotUser
function. gotUser
contains either a returned error (=no user found with that username/password) or a returned user object (a user found with that username/password). Am I right?
gotUser
checks if there is an error. If there is, returns and calls callback
with an error argument. So wait, what will callback
do at this point? Its not defined anywhere. Will it pass the error to an error handler function? And how?
If there is not an error, gotUser
calls callback
again with null
(= no error) and user
. Once again, what will callback do? Why pass the returned user to the callback and not grab its name, mail, age etc etc and use them on a session or fill the innerHTML
of a tag or whatever?
Thanks
So wait, what will
callback
do at this point? Its not defined anywhere.
The value of callback
is defined by the basicAuth
middleware.
You can find its definition within the basic-auth-connect
module, used by connect, in the module's index.js
:
callback(user, pass, function(err, user){
if (err || !user) return unauthorized(res, realm);
req.user = req.remoteUser = user;
next();
});
When gotUser()
invokes callback(...)
, it's call the function(err, user){...}
from the above snippet, passing the err
and/or user
along to be used.
And, how they're used, in the two scenarios you were wondering about...
gotUser
checks if there is an error. If there is, returns and callscallback
with an error argument. So wait, what willcallback
do at this point?
If there is not an error,
gotUser
callscallback
again withnull
(= no error) anduser
. Once again, what will callback do?
The if (err || !user)
condition will pass for both (one has an error, the other is lacking a user). It then considers the request unauthorized
and will end the response immediately.
function unauthorized(res, realm) {
res.statusCode = 401;
res.setHeader('WWW-Authenticate', 'Basic realm="' + realm + '"');
res.end('Unauthorized');
};
Why pass the returned user to the callback and not grab its name, mail, age etc etc and use them on a session or fill the
innerHTML
of a tag or whatever?
The middleware is applying separation of concerns, keeping itself as small and concise as possible. It's goal is just to determine a req.user
and validate it.
When it's done that successfully, other middleware in the application's queue will be able to reference the user
that was found. This can includes using it to render markup from a view:
// determine the user
app.use(connect.basicAuth(...));
// now make use of it
app.use(function (req, res, next) {
viewEngine.render('view', { user: req.user }, function (err, result) {
if (err) return next(err);
res.setHeader('Content-Type', 'text/html');
res.end(result);
});
});
Note: This is generalized and won't run as-is. You'll need to find and setup a view engine of your choice and substitute that into the snippet.
Also, side note on...
fill the
innerHTML
of a tag
Though Node.js is executing JavaScript, it's doing so within its own environment, completely detached from any browsers. It's not possible to interact directly with the DOM currently seen by the user.