Full Web Apps with FastAPI Transcripts
Chapter: Storing data with SQLAlchemy
Lecture: Storing the password securely
Login or
purchase this course
to watch this video and the rest of the course contents.
0:00
The final thing to get our SQLAlchemy stuff really working 100% has to do with storing passwords.
0:07
Now storing passwords is tricky. You wanna make sure you get it right and doing it yourself is probably not the right way.
0:13
So over here, let's check out our TODO's that are pending, says set the proper password. What that really meant is take the plain text passwords
0:22
and set the hashed password to a hashed version. If we just do an MD5 hash, there's these look up tables. This hash equals this word,
0:31
this hash equals this word. We can't do it that way. Also, we wanna make it computationally expensive to guess if for some reason our
0:37
database got stolen and somebody got ahold of those hashed passwords, we don't wanna just hash it once,
0:43
because then you could just guess a bunch of things. So there's a lot of different things,
0:46
like bringing salt that is arbitrary text into, mix it in with the word but also hash folding or password folding, where you hash it,
0:54
and then you take that result and you hash it again, you take that result and hash it again a 100,000 times so that it's really computationally
1:01
expensive to take a guess at a given word, much more so than a single hash.
1:07
So what we're gonna do is we're gonna use this package that makes it much easier
1:10
called Passlib. It does all those things with a variety of different cryptographic algorithms
1:14
really, really easily. So what we're gonna do is we're just gonna go and add passlib and let it do all the hard work for us and get
1:22
things right. So passlib another one to install and it's not misspelled. Now up here at the top, I need to import something from passlib.
1:32
So I'll say from passlib, and I want to import it as a certain thing so if we change the algorithm, we can actually change the underlying algorithm,
1:41
we don't have to change the code just because the name of the algorithm changes. So what I'm gonna write is from passlib.handlers.sha2_crypt
1:48
and here on import sha512_crypt Not like that though, but as crypto. That way, if we decide to use bcrypt or a different algorithm,
2:00
it'll still just be one of these providers, one of these handlers called crypto. Okay, so that allows us little flexibility.
2:07
And down here, this is incredibly easy to use. All we have to do is go to crypto and say encrypt.
2:14
We give it the password, and it also takes a bunch of arguments. See if it'll have documentation inside. Oh, it looks like it was renamed to hash.
2:23
Okay, let's call hash, then. Fine. And the secret is password. Does it say what its keyword arguments are? I know which one I want,
2:30
but I'm not sure, I was hoping for documentation. So what we could do is we could come over and we could say round equals let's say, 172,434.
2:42
So I talked about that folding and do a hash, and you do the hash of the hash, the hash of the hash of the hash. This will do that iteratively
2:49
172,434 times making it computationally expensive. If you wanted to be, take longer, you make it higher. You wanna make it a little bit quicker,
2:57
I'm guessing This is about 1/10 of a second, I'm not 100% sure. Let's go and do this and register a new user and see what gets into our database.
3:05
So register, this'll be Sarah Jones. this'll be sj@gmail.com. She loves the password "abaaaa" and who knows how old she is.
3:16
We hit this, we get our account and let's go to our database and have a quick look. She's at the bottom and now check this out.
3:27
Copy this and I'll just put over this query page here so you can see it Look how giant, enormous that is for, like, four a's and a b.
3:36
This is all sorts of craziness. So it tells you the algorithm that was used, the rounds here, ups don't move that around for me.
3:43
The rounds that were used, the number of iterations and then a combination of the
3:48
encrypted result, along with hash that was randomly created for the salt that was randomly created for it, and so on.
3:54
So this is way more secure than storing plain text. Even better than just hashing it once, right? So it has randomized, per user salt,
4:02
plus the iteration. Really, really nice and how hard was it? It literally couldn't be easier.
4:09
crypto.hash(password). Now, what is not so easy is how do I verify that? How do I verify that that is actually the password.
4:18
Well, what we're gonna do is I'm gonna come over here, we don't have to remember the rounds, it's stored in the result.
4:25
But when we log in, we need to say we're gonna get the password that they provided and we wanna compare that.
4:32
So we're gonna come over here and say crypto.verify. It doesn't say "decrypt" because you cannot decrypt the hash.
4:39
But you can look at all the pieces and hash it again and say, Did the outcome match? So here what we're gonna pass over is we're gonna pass over
4:46
the secret, which is the plain text password And then we're gonna pass over the hash, and that is what we stored on the user object,
4:56
the hash_password. And if it's not verified, We're gonna say no, get out of here. Otherwise it will return the user. So look at that, to use passlib,
5:05
literally that line and that line and we're covering so many good practices around storing passwords, incredible. Let's go try to create,
5:13
let's go try to log in, as our other user. Hope I remember the password, right? It was sj@gmail.com, I think it was "abaaa"
5:22
We'll find out if it doesn't work. No, password's wrong. Let's register a new account. There's no reset. Sarah Jones2
5:29
sj2@gmail.com and we'll set a decent password and register. Now let's log out and see if she can log in again.
5:37
So come over here. Use that same email address. Boom, we're logged in. That's awesome. If I were to put in an invalid password, something else, nope,
5:50
doesn't exist. It doesn't let us log in. So really, really fantastic. This passlib, how easy it makes storing passwords and doing user management
5:58
correctly. FastAPI has other ways of authenticating users and doing authentication. We're not gonna go into it in this course,
6:05
right? Use just this user name and password integration here. But if you wanted to do like Federated Identity or OAuth or stuff like that,
6:11
the framework does support it, but it's sort of beyond the scope of what we're
6:15
doing here to get deep into user management and different types of authentication. Pretty awesome. I'm super, super pleased
6:22
the way this came out, that is the way to do things. And that's a really nice way to verify that
6:29
they are logged in correctly. You saw in the database, go back to our users. Now we'll have a couple examples.
6:34
You look at these two. The number is the same there, but then after that, it's just all randomness, and it's not anywhere near the same thing.
6:43
Super super cool way to store this users in our database.