4.1 Writing Authentication Middleware
We need to protect most of our API's endpoints and ensure only authenticated users can access them. In this lesson, we'll write some middleware to do that for us.
1.Introduction2 lessons, 06:25
2.User Registration and Authentication7 lessons, 1:05:20
3.Wireframing the UI3 lessons, 27:30
4.Handling Requests5 lessons, 39:24
5.Conclusion1 lesson, 01:04
4.1 Writing Authentication Middleware
We are finally ready to start implementing our server side code. And really the first place we should start to is the middleware, for authenticating just about every request coming into our application. Because other than logging in and registering, everything else needs to be protected. So what we're going to do is write a simple function that is going to first of all check to see if we have a bearer token, and then also verify that it is a valid token. If not, then the user is not authenticated, and well, we just won't let them do anything. So inside of our routes, we are going to create a new file called api.js, and we need just about all of the require statements. So let's go to the auth file, let's copy those require statements, and then we will just get rid of bcrypt because we need everything else. Now the reason why I'm calling this API is because, even though we're going to be writing middleware in this lesson, we are going to have the rest of the routes for our API, in this file. So, we will first start with a function called isAuthenticated, this will be our middleware that we will use. So we need the request, the response and next, and the very first thing we should do is check to see if we have that authorization header. So we're going to check that, now it's possible that it's not there, in which case, the result of calling get and then passing in the header name is going to be null. So we want some data to work with, even if it's an empty string. So this way we have something to work with in header, because the next statement is going to change that string into lowercase. So that we can easily find what we are looking for, and in this case, we are looking for the text bearer. Because even though that there is an authorization header, there is no guarantee that it is an actual bearer token. So we are checking to see if bearer, is in the header value, and if it's not, then this is not an authentic request. So we will simply return a status of 401, and then we need to send some data, and we're going to send the same data over and over again here. So, let's do this, we will create just an object called noAuth, and we'll have two things. We'll have an error property that will just simply say Invalids token, and then we will also have a property called noAuth, and we will set that to true. Now the reason why we're going to include this is so that on the client side, we can always check to see if there is a reason to redirect the user to the login. So if noAuth is true, then we redirect the user to login, and we don't have to worry about them anymore. All right, so we are going to send that noAuth object, and that's in case if the request does not have a bearer token in the authorization header. So if we get past here, we can safely assume that we do have a bearer token, so we are going to use our header. And we're going to make the assumption that the header is bearer space and then token, that is the standard bearer token authorization header. So, we are making some assumptions here, but it's a relatively safe assumption. Now it's also worth checking to see if we have this token once again, and if not, we will simply send the 401 status and add noAuth object. So now if we make it pass this, then we can use jwt to verify the token that we have in the header. So we will pass token, and then we also need to use the secret value because jwt needs that value in order to successfully, decode the token, and then we will have a callback function. And the two arguments are an error and then the actual value that was encoded, so we will just call that decoded. Now there's quite a few things that we need to do here because, if we have an error well, then it's not an authentic token. So once again, we will check if we have an error, and if so we will simply return our 401 with the noAuth object. But if we do have a valid token, then we need to use that and find the user. So we'll use the user model we'll findById, and we have the id property, because that is essentially what we encoded. If we go back and look at Auth, let's see whenever we register right down here, we have jwt, we are signing an object that has an id property. So we are using that id, in order to find the given user, and of course, there are two options, either we have an error. Actually there's three, either we have an error, or we don't have a user, because it couldn't find that user, or we do have a user. So, in this case, if we have an error or, if we don't have a user, then guess what, we're gonna return 401, and at noAuth. But if we make it past here, then we do have a user. And we want to make this user object available throughout all of our API routes. So we're going to create a property on the request called reader user, and we will simply sign that to our reader object, so that we can have access to it, and then we will just go on to the next middleware. And so there we go, it's very simple, very straightforward, a lot of repetition, especially when it comes to responding with a 401 and that noAuth object. But that should cover all of our bases, if we have an invalid token or an invalid authorization header, or if we don't have an authorization header then, it is of course, not authorized. But if we do have a token and it is valid, and we can get a user from that, then we simply go on. So there we go that is our middleware, so in the next lesson, we will write the code that is going to retrieve the feeds for a given user. And we will use our new middleware to authenticate that request.