In this video we're going to turn our attention back to the lag in end point and we're going to set
this up to actually generate a Jason Webb token and send it back to the user.
We'll also do the exact same thing for signing up if you just signed up you shouldn't have to log in
in order to start doing things.
We know you're that user because we just created your account.
So both of these requests are going to end up sending back JWT authentication tokens.
That means we don't want to write all of the code for generating the token right here in either of the
handlers because we would need to duplicate it to both places.
Instead we'll create another function we can reuse whenever we need to generate an authentication token
for a given user.
Now we're gonna go ahead and use the function before we define it so we can see what we're getting ourselves
into right here we're going to create a function that returns the token in that token will get sent
to the user.
We'll modify these send call below in just a second.
We can create that function to return a promise.
So we will use a weight to actually get the token back since that function is going to do asynchronous
things.
And right here this function it's not going to be accessible on uppercase U user like we did with find
by credentials.
This makes sense when we're not working with an individual user but we're working with the user collection
as a whole.
In this case though we're trying to generate a token for a very specific user.
So we're going to set up the method to live on the user instance which in this case would be user defined
right here.
So that would be user dot and then we can pick whatever name we'd like for our method.
Let's go ahead and use something like generate off token.
So we're gonna call generate auth token that'll generate the token for this user.
It'll give us the token back and we can send that back to the requester.
So let's go ahead and actually start to put some of this into practice by figuring out how we can create
a new method for an instance of user to do that.
We're going to head over to the user models file once again.
Now down below we already created something similar that was fined by credentials up here we'll add
the new method we'll start off with user schema as we will be setting something on there but instead
of user schema dot statics like we had down below it's gonna be user schema and we're accessing methods
from here we can setup a new method and right here we'll call that what we call it in our other file
that was generate off token and I will set this up as a standard function since we are going to need
to use the.
This binding like we did with our middleware down below.
So I will use an async function not an async aero function.
And right here we'll have access to the ability to write that code so static methods are accessible
on the model sometimes called Model methods and our methods are accessible on the instances sometimes
called instance methods.
So let's go ahead and actually fill this out to generate and return a token.
So we're calling this on a specific user and we get access to that user via this much like we did for
our middleware function.
So const user equals this is a good way to get started allowing us to access user instead of this this
line not necessary it just makes life a little bit easier.
And the next thing we're going to do is generate a JWT using JWT dot sign.
So up top let's go ahead and load this in first.
A new const JWT which gets its value from requiring the following.
Jason web token now once we have the require call in place we can actually use the method down below.
So right here we know we're going to get our token back as we did in index dot J S and we'll be using
JWT dot sign to provide our payload and our secret.
We can pick whatever value we'd like for the secret.
I'll use the same value I had used before.
This is my new course.
So right here this is my new course.
Next up we have to provide a payload that uniquely identifies the user.
And here we're just going to use their I.D..
So we'll set underscore I.D. equal to will then use user dot I.D..
And remember this is an object I.D..
So I'll use to string to convert that to a standard string which is what JWT is expecting.
So now we actually have a token created and we can go ahead and return it from this function.
So right here I'm going to use return to return the token.
And now we can test things out I'll save the User model I'll save the user router to make sure this
code is actually running an over going to do is change what we're sending back.
Currently we're just sending back the user instead.
We're going to send back an object with two properties one the user property will still contain all
of that user data and the other the token property will contain our token.
So here I'm using these shorthand syntax to define both properties.
I'm gonna save the program and we'll head over to the log in request in post man once again.
So over here I have that log in request and in the previous video it did work as expected.
We got our user data back.
I'm gonna go ahead and send it off again without making any changes to it and things is still work.
We still get a two hundred down below though.
We have user data on the user property and we have our authentication token down below.
So at this point we're providing the authentication token to the client and the client can now take
this and make other requests that require authentication.
Now currently no request requires authentication but we're work on fixing that shortly.
Now one thing you'll notice about the current setup is that we're not keeping track of this token value
anywhere on the server the server simply generates it with the correct secret and sends it back.
Now this has an important implication.
Users can't truly log out.
This token as long as it exists means the user is logged in.
So if it gets in the wrong hands a user has no way to log out and invalidate a given token.
We can go ahead and fix that by tracking tokens we generate for users.
This will allow a user to log in from multiple devices like their laptop and a phone then they'd be
able to log out of one while still being logged in to the other.
So all we're going to do is store all of the tokens we generate for a user.
Right.
As part of the user document.
Let's go ahead and knock that out to wrap up the video.
Now to start this feature we're going to head over to users and for the first time in a long time we're
going to add something new on to each individual user.
We have name email password and age down below we'll add a another field.
This one is going to be called tokens and tokens is actually going to be an array of objects.
So right here we set up an array with one item an object.
And right here we can define what each object should look like.
Each object is going to have fields of its own similar to age password email and name.
And in this case we're just going to have one each token in that tokens array will be an checked with
a single field called token token is going to be a string.
So I'll set type equal to string like I've done plenty of times before for other Mongoose fields.
And it's also going to be required.
So if you're going to add a new item and to the tokens array it needs this property right here I'll
set required equal to true.
Now there's no need for any other validation since this is a value that will always be provided by the
server.
So there's no need to do anything like trim it since it's not something the user is typing in or providing
in any way whatsoever.
All we're doing here is providing us a way to store an array of objects.
Each has a token property.
It is the token we're trying to track now.
Down below we can add the newly generated token to this tokens array.
Let's go ahead and get that done.
We're going to make a change to the function we just created that is generate off token and right here
after the token is created we're going to add it to that array and we're going to save the user making
sure that token shows up in the database.
All that means for us is we will be concatenate eating the item onto the array.
So I'm going to set user dot tokens equal to here.
We'll use user dot tokens dogs can cat to concatenate on a new item.
That'll be an object with the token property to find which is exactly what we said we had an array of
when we defined it up above.
Right here.
The token property will get its value from the token variable so I'll use these shorthand syntax to
define that.
Now the only other thing we should do is make sure that we call save so the token does get saved to
the database.
I will await a call to user dot save.
And there we go.
Now we are generating tokens and we're also saving them to the database.
So once again from post man I'm going to log in as the user I'm gonna see that the request works and
I do indeed get a new token back.
And now I'm also getting back a tokens array with these stored tokens.
Now like password this is something we're gonna hide and clean up very shortly but for now it's OK that
it's coming back.
What I want to do is head over to the database so I'm going to crack open robo 3 T.
I'm gonna refresh that user's collection and since I had deleted the database shortly.
This is actually the only user I have.
Right here we have a single token.
If I go ahead and expand the record I can take a look at the tokens array.
I have one item with a single property token.
Now you'll notice that my token document the object in my array of objects it actually has an object
I.D. of its own.
This is known as a sub document and some documents like regular documents also have an object I.D. automatically
generated for them.
Now we're not going to use it but it is indeed there and I wanted to explain why it's showing up alongside
of the property that we actually configured.
So now the log in request actually generates and stores and authentication token and it sends it back
to you from here.
We're gonna go ahead and do something similar for these sign up request up above.
And it's actually gonna be your challenge for the video.
What I'd like you to do is have these sign up request also send back a new authentication token.
So when a new user creates an account they shouldn't need to provide their credentials once just to
provide them again right away to log in.
So sign up will also generate and return and authentication token.
So right here.
Step 1 generate a token for the saved user.
So after we save the user and we know their data is valid you're going to generate the new token using
the function we've already created then you're gonna make sure to send back both the user and the token
as the response body.
And finally you'll test your work create a new user in post man and ensure that you get a token back.
Take some time to knock that out.
Test your work and when you're done click play
how'd that go.
I'm going to kick things off with step number one.
I want to generate a token for the saved user and I'm gonna do that right here after the user is saved.
That'll be a call to user dot generate auth token and we know we get the token back.
So let's create a variable for it.
Const token equals whatever comes back from the function.
Now that function is indeed a synchronous.
So once again we'll use a wait.
Exactly like we had done down below.
Next up we want to modify send it to send back the user end the token right here to do that.
We'll send back an object with both of those as properties.
User first then after that token the last thing to do is to test our work.
I want to create a new user from postman and ensure they do indeed have a authentication token associated
with them.
So for this I will head back over to postman we'll go to our create user request.
Now this email is already taken.
So I'll just add to after it.
So now it's Andrew.
To add example dot com I'll fire off that create user request I get a two a one down below which is
great but what's even better is that I'm getting a token showing up.
So this would be an authentication token that the new user can now use to do authenticated things.