Python for Entrepreneurs Transcripts
Chapter: User accounts and identity
Lecture: Demo: Getting started with logging in

Login or purchase this course to watch this video and the rest of the course contents.
0:04 Back in PyCharm, let's add this ability to track logins
0:07 and know what the logged in user is to our web application.
0:12 The part where we actually do the log in
0:16 is in the account controller on these two methods,
0:18 the signin_get and in particular the signin_post.
0:21 Now, we are going to do a lot of code, juggling some cookies and things like that,
0:25 so let's take that code and put it somewhere else, over in this infrastructure bit,
0:29 I am going to create a file, Python file called cookie_auth,
0:35 and here we are going to use a couple of methods, right,
0:38 so we are going to define a method called set_auth and for set_auth
0:42 we are going to need two things, we are going to need the request
0:45 this is the request that comes into the web action method
0:50 and we are going to want to store the user id, OK, now remember,
0:53 if we look really quickly at our data, where is our user, our account,
0:57 our id is actually a sting which is a fairly large
1:01 I think 32 character alphanumeric string.
1:05 So that is what is coming in here for our user id here.
1:09 now what we ultimately want to do is we want to go to the requests,
1:14 and say set_cookie, now it's going to turn out this is not going to work
1:17 as well as we're hoping but this is the plan, we're going to do it the wrong way
1:21 and then I'll show you a way that works a little better.
1:24 So, next, the question is what do we put into the cookie?
1:27 We could put anything we want in terms of a string,
1:30 I think there is limits but reasonably storing the user id is no problem,
1:34 however, one thing that is a little concerning is if I just put the user id in there,
1:38 what if someone forges a cookie and then just starts guessing user ids,
1:42 because our user id is a 32 character alphanumeric string that alone
1:48 is going to be a super super hard, what we can also put a little verification on here
1:52 to make sure that you can't just stuff user ids in here but to verify that the user id
1:56 comes from our web app, we'll add an additional secret that we can test
2:00 when we get the cookie back.
2:02 So what are we going to have, it's going to look something like this,
2:04 we are going to have the user id, let's just say, I said alphanumeric, didn't I,
2:08 let's say it looks like this and then we are going to in here have
2:11 some kind of hash of the user id, so then when we get it back
2:16 we can look at this number and then we can look at this,
2:19 and make sure "hey, this was the hash we expected to generate
2:23 given that user id" and that will make it much harder for people to guess.
2:27 So let's begin by coming over here and get the hash, hash_val,
2:31 now in order to do this, we are going to use a simple library called the hashlib,
2:35 OK, so up here, we are going to import hashlib, we want to take our hashlib,
2:40 and we are going to sha512 algorithm and we are going to hash this user id
2:46 but you can't give it a string, you have to give it bytes,
2:49 so we can say go over here and code that string, in the bytes, using utf8.
2:53 And what we get back is a hash object, and we don't want a hash object,
2:57 we want a string, so we can say give me the hexdigest of that,
3:01 and let's just print out the hash value here just so you can see
3:07 what is coming on, and comment this out.
3:09 So let's just run this to make sure everything is coming out good,
3:12 it turns out we are going to hash something else in just a moment.
3:15 So let's come over here and we'll say first we import a cookie_auth alright,
3:23 so I want to come down here we are just going to call cookie_auth.set_auth on account.id,
3:29 OK, so here we sign in, we get the authenticated account,
3:33 either we get nothing and we tell them an error
3:35 or we get the actual account back then we'll have access to its id
3:37 and we should see what is going to happen here.
3:42 So, let's go sign in, I'll just use my saved credentials, this is from the last video,
3:46 I just remembered them, we are not passing the user id apparently.
3:50 Oh, we are but we are not passing, what we really need to pass is the request,
3:55 we didn't technically use that so I forgot about it,
3:58 but we are going to use it in just a minute, let's try again.
4:03 Alright, so here you can see this is this huge hexdigest,
4:08 alright, but this should be fine for what we're doing,
4:11 it's huge but a 120 characters, not that huge.
4:15 Alright so what we want to do is we want to create the value
4:17 and we'll say the value is going to be the user_id: the hash.
4:22 Here we'll just say user_id, hash_value.
4:26 alright, so our goal is going to be to take this and actually set the cookie.
4:31 So setting the cookie is really easy but it turns out there is going to be
4:35 a little catch that we need to be aware of,
4:37 so I want to make sure you run into it so you understand this
4:40 sort of slightly more complicated version that we're going to have to go through.
4:43 So I'll call this auth_cookie_name, and let's just call this blue_yellow_auth,
4:52 or user something like that.
4:55 So we're going to have to ask the browser for this cookie,
5:00 and then we're going to tell it to save it, so what we do is here we say the cookie name,
5:03 we say the value and then we say the timeout.
5:13 So let's say we'd like to save this log in cookie,
5:15 for either 30 days in which it will expire or until they log out
5:19 and we'll talk about logging the out in just a minute.
5:23 Now you would think, you would think that this is going to work.
5:27 However, let's find out. So I rerun this, I go over here and refresh
5:32 and if we go and actually look in the network tools,
5:36 let's do one more request there we go, and only see HTML, OK, great.
5:44 So if we look at this and we look at the cookies,
5:46 you can see that PyCharm has inserted some kind of cookie for us
5:50 because it wants to be able to debug this request, right,
5:54 this is basically running in the PyCharm web server right now,
5:57 but the cookie that we added, it's not there.
6:00 So that's weird, and it turns out this is just some bizzare thing, with Pyramid,
6:06 somehow the combination of all the pieces
6:09 we're using kind of dropped the cookie along the way.
6:13 Oh, actually one mistake I did make, this is supposed to be response cookie,
6:18 obviously, so let me just verify one more time that it's still not setting the cookies.
6:23 so we click on it, still not setting the cookies, so request we get the response,
6:27 we tell the browser "set this cookie", it didn't set it so this turns out to not work,
6:32 as well as we're hoping and the way to make it work is we have to
6:36 hook into a different point in the life cycle of Pyramid.
6:39 I feel like this is a bug, at least in extreme shortcoming,
6:42 I don't really know why this is happening but it's easy enough to solve
6:46 so let me show you how we are going to do this,
6:49 we are going to have a function here,
6:52 and I am going to hide it from people importing this module that we created here
6:55 so use a double underscore,
7:00 so we are going to have add cookie callback and in here,
7:03 I can do this code basically, adjusted for what I changed names here
7:08 so this is going to be value, this is going to be plain name
7:11 and this will be the request and let's go ahead
7:14 and also do this way I think we can just do it response.set cookie.
7:18 So how does this get called, right, if we don't do it up there?
7:22 Well, what we're going to do is we are going to tell the request:
7:24 "hey, when you are just about done, call this function for us."
7:28 Let's put nothing there.
7:30 So we are going to say add response callback
7:34 and this thing takes two values, directly, so it takes the request and the response
7:40 but I also want to pass the name of the value
7:42 so I can create a function that is a closure
7:45 that we could pass those along, so I'll create a lambda,
7:48 of request response and in here I am just going to call this function,
7:52 and I am going to call it with of course the request, the response, that's passed through
7:58 in the lower levels of Pyramid and then I am just going to give the cookie name
8:02 which will be the auth_cookie_name and I am going to give it the val.
8:06 OK, so instead of trying to set it directly,
8:08 we are just going to say "hey, do a callback, set it here", let's try again.
8:12 Reload the page, and now we're going to need to set the cookies,
8:17 so let's go to our sign in, now if we look at our GET, check it out,
8:23 our blue_yellow_user is here and then there is the log in.
8:26 So you can see setting cookies is super easy, there is this weird catch
8:31 where you've got to do it through a callback but really it's not hard at all to set.
8:35 So this cookie will be around for 30 days and then we can ask for it,
8:38 so the next thing we're going to do is we are going to go and actually
8:41 read this cookie and make it accessible to the rest of our web application.