Full Web Apps with FastAPI Transcripts
Chapter: Users and HTML forms
Lecture: User sessions via cookies

Login or purchase this course to watch this video and the rest of the course contents.
0:00 Got a little bit more work to do here,
0:02 and I guess we could take away the TODO on this one.
0:04 But now we're gonna need to log in the user.
0:06 How are we gonna do that?
0:08 Let's go and create a special class that manages putting the user information into cookies and
0:13 getting it back out of cookies,
0:15 checking what is there and so on.
0:16 Because we'll see there's a naive way we could do pretty quickly inline here and
0:20 a more complex way, that works a lot better.
0:23 So let's go create a new category of code called infrastructure.
0:28 This is like stuff that helps out the rest of the site.
0:30 Little utilities like converting integers or
0:32 pulling out cookies or stuff like that.
0:34 And I'm gonna call this thing, we're creating cookie_auth.
0:38 What we're gonna do is we're gonna take two passes at this.
0:41 I'm gonna show you a simple version that has a problem and then a more interesting
0:45 version that we're just gonna drop in here and review that's like this,
0:48 but better. So we're gonna have to functions here.
0:51 One I'm gonna call set_auth and it's gonna take a user_id and
0:55 all it's gonna do, it also needs a response,
0:58 which is a Response from Starlette,
1:01 and this is gonna be an integer.
1:04 Then we have another one called get user id from cookie, from auth cookie.
1:14 And I think this is gonna need a request.
1:18 Same one that we've been working with the whole time, from Starlette. And we don't pass in
1:22 the user_id because we don't know, we don't have it yet.
1:27 That's what we're doing here. It's gonna be Optional integer from typing, perfect.
1:33 So let's go over here and use this cookie_auth, so cookie_auth and I need
1:40 to pass it this before we send it along.
1:43 So there's a response. Here's our redirect.
1:49 And then we need to say set this cookie here before we send it along.
1:52 So the response is gonna go there,
1:55 and the user_id, we'll say account.id, doesn't have an id yet,
1:58 but we will go and update our class to
2:00 have one. So do that real quick.
2:06 Let's say it's always 1, until we get to the database where it'll autoincrement.
2:11 Alright, so I'm gonna pass that along and then it's gonna be really simple.
2:14 All we gotta do is go to the response and say, and our first pass is
2:18 gonna be simple. At least set_cookie, the key,
2:22 let's make sure we always use the same key.
2:24 So, like the name of the value in the cookie dictionary,
2:28 this will be auth_key. It's gonna be,
2:31 let's say, 'pypi_account' like that.
2:36 So the name is gonna be that, the value that we wanna pass in is
2:40 the string of the user_id, the max_age.
2:44 Ah, we don't need to set the max_age,
2:46 there are a couple of settings we do wanna set
2:48 though, we want to set secure,
2:51 and we're not going to set it here,
2:52 I'm gonna say False. But in your real web app,
2:55 when you're running in production, you wanna set this to be True so that
2:59 if somebody types your domain without using HTTPS,
3:03 it won't still exchange the cookies over HTTP,
3:05 where people could eventually watch it.
3:08 But I'm gonna say False in development because we don't have SSL set up in development.
3:12 And then httponly, this means that JavaScript code cannot read the cookie.
3:16 It'll exchange it, but it can't read it.
3:19 So I'm gonna say True and samesite being "lax",
3:22 that's good. All right, I think we're in good shape with this.
3:26 And then over here, we wanna read it back.
3:28 We wanna take our request. I'll say,
3:32 if auth_cookie not in request.cookies,
3:39 then we'll return None, there's no value here. And let's, for now,
3:43 just say we're gonna directly store this as a string,
3:46 so we'll say user_id equals, notice
3:52 it's dictionary-like so the way we access it is auth_key like this.
3:56 Then we need to convert this to an integer like so and return it.
4:01 Right, so what we're gonna do up here, we're gonna call this, which we are.
4:05 And then let's go and actually make our view model Do the magic that it
4:09 was supposed to do all along.
4:11 Remember we said you're logged in,
4:12 yes or no. Let's go like this,
4:14 Let's say cookie_auth, get user_id from cookie self.request so the request
4:21 is passed in. All right,
4:22 and if that comes back with something,
4:24 well, we should be logged in.
4:25 If it doesn't come back with anything,
4:27 we won't be logged in. Let's go ahead and give this a test and see how
4:29 well we've done. But first of all,
4:31 notice we're not logged in, so this "Login" and "Register" are set,
4:35 that's a good idea, a good sign.
4:37 Let's go over here and register with all the info that I put in.
4:40 Oh, yeah. I need my five a's and let's just put anything there.
4:44 So this works, it should set a cookie.
4:46 Let's go over here and see if we can get it to show us while we're
4:49 at it. It should set a cookie,
4:53 then redirect us to the account page.
4:55 The account page, all the pages, will look and see if there is a login
4:59 cookie and should switch this to "Account" and "Logout".
5:02 If it doesn't do that, we got something wrong.
5:04 Let's see how this works. Off
5:07 it goes, yes, perfect.
5:10 So check this out, "Account" and "Logout" are now set over here.
5:14 And here we go. We've got our account information there,
5:17 if we go and look at this you can see set-cookie
5:21 pypi_account, is id equals 1,
5:24 HttpOnly, Path is what it is,
5:26 SameSite is "lax", like we described.
5:28 Then when we did a GET over here,
5:30 the response had over here in the cookies, had that pypi_account
5:33 is one. I think we've got this working.
5:39 We've got our cookie set up.
5:40 At least in this naive way,
5:42 we just have that stored in a cookie.
5:44 And if it's set, then we're logged in.
5:46 We pull back that user_id, if it's not set,
5:48 hey, we must not be logged in.