Fixing Session Expiration Behavior in 2FA Disablement Flow
00:00 So let's come into our session server right here, and we're going to override the sessionStorage.commitSession. So to be able to do that, we need to still call the underlying method. And so what we're going to do is have an original commit session so that we can still call that function when we need to.
00:19 OK, and then to override it, there are a couple of ways you can do this to monkey patch it. You could use the proxies and the Reflect API and all sorts of interesting things. I think the most straightforward way to do this is with object.defineProperty. And here we're going to have a value. And this function is actually async.
00:38 And we're going to take all of the arguments. We'll call this args. And then to make this type nicely, we'll say parameters of type of original commit session. And that's going to be just basically we're resembling the exact same API as the original commit session.
00:58 So with that now, we can get the session itself. That's the session object that we call commit session with. And then also, we have the options for configuring the cookie. And we're going to get that from the args. OK, so from that now, we just need to say if options expires, which options is optional.
01:17 So if that exists, then we're going to set expires to be whatever options expires was. So we're going to set a new key, a new property within the cookie. It's all kind of a hidden thing. But yeah, it's going to be set for us. If there's a max age, that's another way that you can configure this.
01:36 We need to calculate what the expires time would be, and then set that to the expiration there. And we can just set it just like that. Thank you, Copilot. OK, so with that now, we need to access what the expiration should be.
01:51 And so if the session has and expires, no, that should be has. There we go. If it has expires, then we're going to take or get the expiration value out of the session. Otherwise, it's going to be set to undefined. And then we get our set cookie header,
02:10 which we're just going to call the original commit session. We'll spread all the options that they provided us, but we're going to explicitly set the expiration. This is the piece that is going to make what we're doing possible. And with that then, we can return the set cookie header, and we should be golden.
02:27 So we've just overridden the commit session function of the session storage so that we can do a couple of things before calling the original commit session. That way, we can keep track of the expiration as a part of our session. So let's see if this works.
02:45 We're going to log out, and we're going to move this over so we can take a look at our cookies right here. We're going to log in. Cody, Cody loves you, and remember me, and then log in. So we've got our verification. It's not our session yet.
03:03 So let's generate our one-time password. And here's that. Paste that in here. Submit. And our expires is still in a good place. We're on our session. Everything is golden. So now we come over here. We're going to edit profile. And 2FA is enabled.
03:19 Let's make sure that our login is set to not two hours, but five seconds to require revalidation. So when I click on Disable 2FA, it's going to take me through this process. And so let's generate another 2FA right here.
03:37 And paste that code in and submit. And we are in a good place. Now our expires has stayed the same. We can also take a look at our Network tab at that last post request. And the response headers should include a cookie for Ian's session. This is setting our verified time. So we know the last time that this was verified.
03:56 And it will contain our expiration to be on the right day. So we're in a good place here. Solved the problem with kind of, honestly, it's a bit tricky. I'll be honest. It is unfortunate that we have to deal with this. But it actually works out pretty well. And honestly, I think it's a pretty elegant solution.
04:15 Because we don't have to change our code all over the place. We can just have this one place where we kind of explain what the problem is. This is a web platform problem itself. Anytime you are going to commit a session, anytime you create that cookie, you have to include the expires. And we don't know, just from wherever
04:34 we're calling commit session, whether the user wanted to remember their session. And so we're going to kind of manage that for ourselves inside of a little bit of a, there's a little bit of logic here, but to find property magic. But it still works. It's all still type safe. We've got everything under control.
04:53 So yeah, let's just quickly review. We're overriding that commit session function. We're setting the value to this async function that takes the exact same parameters as the original. We're grabbing the session that's going to be provided. So if we take a look at our, let's see,
05:11 yeah, on the login right here, where we say commit session right here. So this is what we're calling. We're passing this cookie session and optionally passing these options. So we're going to take that session and those optional options. And if options.expires is defined, then we'll set that in the session. If maxAge is defined, then we'll calculate
05:31 what the expires should be and then set that. And then we're going to take our session has expires. And if it has expires, then we're going to pass that through. Now, actually, one other thing, I just noticed a little bug here.
05:47 maxAge is actually calculated or is specified as seconds rather than milliseconds. So we actually need to multiply this by 1,000 for this to be correct. So we get the expires, and then we set that as part of the options for the original commit session so that we always pass the proper expiration.
06:06 And now we don't have to change any of the rest of our code. It'll always just work. Well done.