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

Talk Python's Mastodon Michael Kennedy's Mastodon