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 calls callback with an error argument. So wait, what will callback do at this point?
If there is not an error, gotUser calls callback again with null(= no error) and user. 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.
There are a couple of different things going on. For one, app.use expect a function that will be called with req, res, and next. When you run connect.basicAuth, it runs this method.
Since this is a middleware method, this method will run every time a route that was defined after this method is hit.
The second thing that is going on is connect.basicAuth is a function that will be called with username, password, and a callback method. Callback is something that connect.basicAuth provides.
If you return callback(err), it will send a 401 Not Authorized back to the client. If you return callback(null, user), it will continue until either the next middleware function, or the appropriate route.
Related
What is the purpose of the res.render callback argument?
In which case would one want to use such a callback argument, since a template is already assigned as the first argument?
Here's the code from the documentation:
// send the rendered view to the client
res.render('index');
// if a callback is specified, the rendered HTML string has to be sent explicitly
res.render('index', function(err, html) {
res.send(html);
});
// pass a local variable to the view
res.render('user', { name: 'Tobi' }, function(err, html) {
// ...
});
I understand the purpose of the first two arguments, but not the last.
With the callback, you can intercept the rendered template before sending it on. You might want to minify it or otherwise modify it before sending to the client.
From the documentation:
If provided, the method returns both the possible error and rendered string, but does not perform an automated response.
Newbie question while trying to understand code created by others. Believe me I tried to understand this. Here goes..
For what reason would someone still call functions like .qs() and .json() in Request - module after we got what we need with .post() and sent the response already. They can't affect the request.post as they are called afterwards, can they?
With my skills I'm not able to understand from response module API docs (v2.22.0) what these actually do.
This is not the whole code but I tried to get the important parts here:
// When request comes to /getthisapge, make external query and return data in JSON format.
var request = require('request');
module.exports = function(app) {
app.get('/getthispage', function(req, res, next) {
var filter = {};
var query = {};
filter.category = req.query.category;
query.onBehalf = req.query.onBehalf;
request.post(URIandoptions, function(error, response, body) {
res.json(body.members)
}).qs(query).json(filter);
}
}
Without knowing exactly what the post function does (unnecessary to your question), you need to look at the order of execution.
request.post(URIandoptions, function (error, response, body){
res.json(body.members)
})
.qs(query) // ?
.json(filter); // ?
The function passed into post() does not get called at that specific moment. It is given to the post() function to do with as it pleases. This means technically that the function may never be called (depends on the api).
qs() and json() both get called upon the returning of the prior function. Usually this type of api means the following:
call post(), passing in a function to be run on completion
call qs() to setup the query details
call json() to tell the post function how to act, which in turn executes the actual post, running the completion function after data has been retrieved.
var server = require('http').createServer(app);
server.on('request',function (req, res) {
res.end('asdas');
});
How can I know which callback, with how many of arguments, should be passed?
I saw some tutorials, and in some cases callbacks have other amounts of args, like: data, err, message, req, res. Is it somewhere in Node.js docs and it depends on first argument passed into .on() function, or it depends on request type coming, or can I modify it in some my own way, or what?
See the docs.
The request event is emitted with two arguments, request an response. Your code is correct.
The express route is setup with the following
var users = require('../../app/controllers/users.server.controller');
// Set up the 'signout' route
app.get('/signout', users.signout);
However, since the parenthesis aren't present, this means that the function users.signout is being passed and not executed?
The file on github can be found here
The users.signout function looks like the following
// Create a new controller method for signing out
exports.signout = function(req, res) {
// Use the Passport 'logout' method to logout
req.logout();
// Redirect the user back to the main application page
res.redirect('/');
};
The file on github can be found here
Why is users.signout executed? And how does it get passed the req and res parameters?
When you use
app.get('/signout', users.signout);
Express.js basically stores the given function, users.signout, internally and keeps the association with the /signout path.
When a request is made on this route, Express.js will get the corresponding stored function and call it, roughly in the following form:
// `storedFunction` corresponds to your `users.signout` function
storedFunction(expressReq, expressRes, expressNextCallback);
If you were to call you users.signout function in the call, i.e.
app.get('/signout', users.signout());
you wouldn't be able to get the req and res parameter and the users.signout function would actually execute right away, meaning the app.get function would actually receive the result of your function.
You can read more about this in the documentation. Hope it helps!
The express app.get function takes a string as the first argument and a function as the second. When the app listens to the routes and finds the route '/signout' it executes at that instant the function you gave in the second argument passing to it the req and res objects.
The function is not executed at the moment of the declaration app.get('/signout', users.signout);.
The same code could have been written as (assuming that you are using Passport to be able to use the logout method):
app.get('/signout', function(req, res) {
// Use the Passport 'logout' method to logout
req.logout();
// Redirect the user back to the main application page
res.redirect('/');
});
and it is actually a function which is passed to the second argument of app.get, but with explicit declaration of its logic in the same place.
I'm an node.js and express.js noob. This question may seems silly but I'm really in confusion.
I'm trying to configure Local Strategry authentication by using passport. As shown in the official documentation, we can figure this Local Strategy by the following code,
passport.use(new LocalStrategy(
function(username, password, done) {
User.findOne({ username: username }, function (err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false); }
if (!user.verifyPassword(password)) { return done(null, false); }
return done(null, user);
});
}
));
My confusion is about the done callback function. When the official docs show this local strategy using as a middleware in the route handler, there is no need to pass the function parameter for this done callback.
app.post('/login',
passport.authenticate('local'),
function(req, res) {
res.redirect('/');
});
So, isn't this done callback function will be null if we don't provide the function parameter? If not, what is that done callback function and what processes will be happening in this done callback function?
done is a method called internally by the strategy implementation.
Then it navigates you, as you can see, to one of the success / error / fail methods (again, by the implementation. there are more options).
Each of these options may calls to the next, where in your snippet code is the following:
function(req, res) {
res.redirect('/');
});
When success is called, it can attach the user to the request or do other things, depending on your needs (it looks for the options you pass to passport.authenticate). If you want to determine when next will be called, you should use custom callback which gives you more flexibility.
I strongly recommend that you read the source.
It's now 2022 and I had the same question. The passport documentation has improved and it describes the done method (also called cb) here: https://www.passportjs.org/concepts/authentication/strategies/#verify-function. You will need to call this yourself in your strategy's verify function.
A verify function yields under one of three conditions: success, failure, or an error.
If the verify function finds a user to which the credential belongs, and that credential is valid, it calls the callback with the authenticating user:
return cb(null, user);
If the credential does not belong to a known user, or is not valid, the verify function calls the callback with false to indicate an authentication failure:
return cb(null, false);
If an error occurs, such as the database not being available, the callback is called with an error, in idiomatic Node.js style:
return cb(err);