The Role of Sessions in Web Applications
Alright guys, so welcome to another video. In this video we're going to go ahead and talk about sessions in NestJS.
So what I'm going to do is I'm going to show you guys how we can actually enable sessions so that way we can actually have more persistent, uh, we can have a more persistent application. Sessions are basically very important for any application that has to have state because by default HTTP requests are stateless. Every single request made to the server is independent from each other and it doesn't really tell you anything about the previous request. So we don't know who the user is logged in, we don't know who they are, and the way we solve that is by using something called cookies. So with sessions, basically, you have sessions enabled on the server side and sessions will pretty much take care of generating an ID for that session, and that ID will be used as a cookie on the client side. Okay.
Installing Session Dependencies
So what we're going to do is we're going to go ahead and install a couple of packages. So what I'll do is I'll simply just go over to my project, or go into my terminal. We'll do yarn add express-session, and then we'll also install the types as well since we're using TypeScript.
Alright, so now we have installed the types.
Registering Session Middleware in NestJS
Let's see. So yeah, yep, perfect. Okay. So now we just go into our application, we go into the main.ts file. So it's very similar to how you do this in Express, it's really the same thing. So what you do is you just register the middleware by calling app.use() and then you want to import the session. So what we'll do is we'll simply just do import session from 'express-session'. Okay. Uh, and we also want to do one more thing, and we need to also import passport as well. Now you don't need sessions to work, you don't need passport for sessions. But because we already used passport in the previous videos, I'm just going to do something that we did not do already, and that's just making sure that a passport is enabled with sessions, because passport can actually work really well with sessions. So whenever the user is logged in, it'll basically save the user to the session so that way we'll know who the, who the authenticated user is. So I'll do that as well.
Configuring Session Options
Okay. So first let's register the session. So what we'll do is we'll go ahead and set the secret. So this is the secret for the session, well it's basically going to be responsible for how we're going to encrypt the session ID as a cookie. So you want to keep this an actual secret. Don't give this to anyone. If they use that, if they had it they can literally decrypt the cookie, and you don't want that.
We're going to set resave to false. So this will basically prevent the session from being forcefully resaved to the session store. Uh, so typically you'd want to set this to false, okay?
And we'll also set saveUninitialized to false. So this will prevent saving sessions that have not actually been initialized. So what that means is, let's say for example, if the user just visits your website, they don't log in, they don't create a new account, then you don't want to usually initialize a session for them. Uh, you don't want to, like, you know, you don't want to like give that session to them. Instead, you want to allow the user to log in and once they log in, then you'll initialize a session. So setting this property to false is what you'd want to do.
There's also other things that you can set too. So for example if you provide the cookie property, you can set the maxAge of that session. So you can have it be like, for example, one minute and at the moment it will expire. You can also set the session or the cookie to be a secure cookie. I don't know why my IntelliSense is in the way all the time, you know. There you go. It's just like really right over there which is so annoying. There you go. So you can set it to be secure, you can set httpOnly, sameSite, signed, whatever it is. maxAge will be fine.
Accessing the Session Object in a Controller
So now that we have the session middleware enabled, you can actually uh integrate this with passport just fine. Or you can, you know, let's say for example if you don't want to use passport, you have your own authentication strategy. You can actually directly uh interact with the session object itself by using the @Session decorator.
So for example, I'll show you guys that real quick. Let's go over, let's create another endpoint just for fun. Let's do that inside the auth module. So I'll just make this a GET request and we'll just leave this as is. And we'll just do async getAuthSession. And what I'll do is I'll simply just do @Session() session. Okay. And uh, yeah, I think the session does come from the actual NestJS common package. Yeah, this decorator. Yeah, perfect. Okay.
And so the session is going to have a key-value pair and the type is going to be a record, and it's just going to be a string of any. That's really what the session is, it's a bunch of key value pairs. And for now what I'll do is I will log the session, and let's go ahead and access this endpoint.
I think we didn't start the server up. Let's do that real quick.
Exploring the saveUninitialized Setting
Okay, now if I look into my Postman, you'll see that I actually don't have any cookies. Okay. If I call GET, I shouldn't get a cookie which is fine because we have saveUninitialized to false. And now if you look at the logs you can see that this is what the session looks like. Okay.
Now you can also do other things too such as if you want, you can get the session... I don't know why. There should be a session ID. Uh, there should be like a session ID right over here. I think it's session. Yeah, there we go. So every single time I make a request and move this through the screen, you can see that it gives us a new session ID. Okay. So every single time I make a request it gives us a new session ID. Okay.
Now if I go back into uh, if I go back into our configuration and, and just let you know, we have not done anything with passport yet. I've only imported passport but uh, I'm not going to do anything with that just yet. So let's say for example if I set saveUninitialized to true, look what happens uh when I click on, if I'm going to send the request right now. So you'll see that this is the session ID. On the browser you can actually look for this value on the browser. Um and I'll show you guys that later. But if I click on send again, you'll see that the session ID is going to be the same every single time. Okay, it's going to be the same every single time. So it gives us a new session ID. Okay.
Inspecting Session Cookies in Postman
Um, so now let me do one more thing. Let me change this back to false. And let me go ahead, and you also notice that in Postman it also shows the cookie right over here. And you can see that uh, this is actually how it would look like in the browser as well, or whatever, you know, client you're using to make POST requests or GET requests, or really any request. You'll see the connect.sid, which I guess SID stands for, I'm assuming SID is short for session ID. You can actually change the name of that too.
Um, and you can see right over here, uh, so everything up from, I think it's everything after 3a so s:2v2... uh, it seems like it's too late, we have to make another request. So let's send a request. I think, oh yeah, I think our cookie actually expired. Let me, let me actually do this again.
Let me go back here and let me also change the name of the session to just be uh nestjs-session-id. Okay. So we'll set it back to saveUninitialized set to true. But like so, most of the time you'll want to set this to false because you'll also, you'll also want to make sure you, like, you know, enable a pop-up that asks the user to allow cookies because obviously you can get into trouble for that.
Anyway, so you can see this is the NestJS session. You can see that, uh, so if I go over here you can see that this is the session ID, 4l2-hwlks. And then you can see that right over here, we can see that all the way up until this dot. That's a session ID. Everything else basically allows you to basically, it's used to decrypt the cookie or sign the cookie in other words. Okay. But this is the actual session ID. Okay? It's just, it's just, you know, encrypted and sent to the browser and saved as like an actual, uh, saved as the next cookie.
You can see that it expires very soon, in about a couple seconds it's going to expire. And you'll see that in just a couple seconds if I, if I make that request again, it's going to show the same cookie again. Okay. So, uh, it should expire just now. Yep, just expired just now. If I clean cookies again, you'll see that the cookie is removed from the client because it expired, and that's what Chrome does as well. And if I go ahead and if I click on send again, it's going to give us a new cookie. Okay, so that's pretty much how that works. Okay, but uh, like I said, by default you want to set this to false. Okay.
Manually Initializing a Session
So now how exactly do we make it so that the user is actually, or the cookie is actually initialized, where the session's actually initialized? Well this works the same way when you use sessions with express. So basically as soon as you modify the session object, so for example if you do session., that's not session.id, let's do session.authenticated = true and we'll just return the session. Okay. As soon as you modify the session, that is when, uh, that is when it's considered initialized. Okay.
So let's go back to our configuration, let's make sure that saveUninitialized is to false, and then we will basically manually update the session object. Okay, and when this happens it will actually initialize a session. So watch what happens. So let's go to the logs. I'm going to go back to Postman. I'm going to go ahead and click on send. You're going to see that it sends back authenticated: true and you'll see that this is the cookie. So the ID of the cookie, or the ID of the session should be v-a-v, v-a-y-r-u-k, and you can see that's what it is right here. If I click on send again, it's going to log the same exact session because every single time we, we, every single time you modify the session, it's going to initialize a session. Okay.
So let's just wait a couple of more seconds. So, three, uh, in about, about 20 seconds it should expire and we can make a request again and what will happen is it will authenticate or it will set that value authenticated to true, and that will modify the session object, and that will consider the session to be initialized. And as soon as that happens, that means the same cookie that we got originally when we got initialized will be the same cookie that will be given every single time. So that's pretty much how under the hood the login mechanism works. That's actually how it happens with express or passport.
So the cookie is gone. If I click on send, it gives us a new cookie. It's a completely different new cookie. If you look in the logs, the cookies are entirely different. Okay.
Next Steps: Integrating Sessions with Passport.js
So, uh, yeah, that's uh, that's pretty straightforward when it comes to sessions. Uh, now obviously we need, we need the sessions to work with, um, we need the session to work with, um, with logging in. Okay? Because right now if I try to log in, so if I try to log in, it doesn't give us a cookie. And that's because by default, passport won't actually, like, enable sessions with us. We need to actually do that ourselves in order for that to actually work.
Now, in order for us to actually get sessions to work with passport, it's a whole process, so I'll save that for another video because, um, we need to register all the middlewares, and then we also need to set up a serialize and deserialize function. Uh, so I'll save that for the next video, and in the next video is where we're going to actually have like a full actual authenticated application up and running. So I'll see you guys in my next video. Peace out.