4.4 Configuring Middleware
In this lesson we'll see how to add custom middleware to our applications and how to take manual control of the middleware sequence.
1.Introduction3 lessons, 11:27
2.Sails.js From the Front-End2 lessons, 20:07
3.Sails Blueprints2 lessons, 13:34
4.Building the Back-End7 lessons, 58:40
5.Additional Techniques2 lessons, 09:55
6.Conclusion1 lesson, 01:28
4.4 Configuring Middleware
Hi folks, in this lesson we're gonna see how we can provide configuration for any middleware that we want to use. In the last lesson we installed Passport for easily authenticating our users. Now let's move on to provide the configuration that Passport needs. So first of all let's add a new file to our config directory to handle this. And let's call it passport.js. All the files in the config directory are automatically loaded when we lift our app, so the middleware configuration here would be visible to any other module that requires it. So first of all we need to require in Passport and the passport-local strategy, as well be bcrypt. To configure the strategy, we use the use method of the passport object. So the use method needs to be past a new instance of a strategy, so we use the new keyword to invoke the local strategy constructor. And we pass it a callback function. This callback function will be passed the username, password, and a callback, which we'll need to invoke once we're finished. We can use the user object to look for a user with a matching username. So we use the findOne method and it's very similar to the find one method that we used with Mongo earlier in the course to look at the records we stored in the Mongo database. And we pass it two things. The first thing is a configuration object that specifies how we want to find the user that we're interested in. And we specified that we're gonna be using the username. And we pass in the username that was passed to the callback function. And the second argument is a callback function that will be invoked once the findOne method has finished. And this will be passed, maybe an error object and the user object that gets found. So inside our callback, let's first handle the error if one exists. So if there is an object, we can just invoke the done callback and pass it the error object. So next, we can handle the no matching user case. So this time we're invoking the callback method with three arguments. The first argument is the error objects, which in this case is null because we already handled the error if there was one. The second argument is the user object, which is false because we didn't find a user. And lastly, we pass back an information object within which we can set the message property to a string containing and error message. The done callback in this case will invoke the callback function we pass to the authenticate method that we added to the UserController in the last lesson. So it's this callback function which is invoked when we invoke done. So we've handled the error case and we've handled the non-matching user case, so now we need to handle the successful case. We want to compare the password passed to the local strategy constructor with the password for the user from the database. And the password in the database is encrypted. So we need to use bcrypt's compare method to compare the unencrypted password and the encrypted password. So we use bcrypt's compare method and we pass it the password, the user's password, and a callback function. And the callback function will receive an error object and a result object. If the result object is falsey, the password compare was unsuccessful, so we can invoke the done callback with the appropriate arguments. Again, we pass null as the error argument, false as the user argument and a message that the credentials were not recognized. For security we don't want to tell the person trying to authenticate whether it was the username or password which was wrong. We just say that the credentials aren't recognized without being specific. Lastly, if the function hasn't yet returned, then we know that everything went according to plan and the user authenticated successfully. So this time we can invoke the done callback with the user object and a success message Now we just need to make a slight modification to our middleware configuration in config/http.js. So by default, Sails handles the middleware configuration for us and what we want to do is just handle that ourselves. So let's un-comment the middleware property first of all. And then we need to un-comment the order array, and some of the items inside it. So first of all, let's just uncomment everything. There we don't want to use this myRequestLogger because that's an example of some custom middleware and that's gonna stay commented out. And we now need to add the middleware items required by Passport. So first of all, at the top of this file we need to require in passportInit and passportSession. And we can add these to the order array, and they just need to come directly after the existing session item. Great, so that should be all we need to do in the backend, and we should now be able to do some testing with Postman. So, first of all let's re-lift Sails and just make sure it lifts okay. So it can't find the module bcrypt and the reason for that is because we're using bcrypt-nojs. And this time it's lifted successfully. So first of all let's use Postman and try and signin without sending any parameters whatsoever. So, we see our message that the credentials are missing, okay, that's fine. So now, let's try adding a username that doesn't exist. And this time we see our message that the credentials were not recognized. And the previous error message, sorry that's the credentials were missing, that's a built in one from Passport that we didn't need to add ourselves. The credential's not recognized with the exclamation. That is the one that we did add ourselves. And we can see that back in Visual Studio as this message here that we're seeing. And I've just noticed the typos, so I'm just gonna fix that as well. So this time, just to round off our testing nicely, let's just try it with a good user but the wrong password. And again we see the same message that the credentials aren't recognized and it still has a typo because I haven't re-lifted Sails. And lastly, let's just try it with all of the correct information. And this time, we see the status of 200, it hasn't sent back the message that the sign in was a success. And the reason for that is because we're not passing that back from the controller. We're just sending back res.ok(), so that sends back the 200 state. Great, so our authentication seems to be hooked up correctly. Users won't be using Postmen to make requests, of course, they'll use a signin page. And we'll come back and add this in the next lesson. So in this lesson we saw how we can add our own custom middleware configurations to the config folder. And how to enable a custom middleware sequence using the http.js config file. We also learned that any files that we place in the config directory will get loaded by Sails when we lift our app. Thanks for watching.