Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Well done!
You have completed Flask REST API!
You have completed Flask REST API!
Preview
No one wants to send their passwords around in plain text all the time. Giving users a safe and secure token to use will make them feel better.
Related Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign upRelated Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign up
Sending usernames and
0:00
passwords in plain text across
the wire isn't the best solution?
0:01
I know I don't feel safe doing it and
I'm sure you don't either.
0:05
So let's give our users a safer way
of sending most of their requests
0:08
by creating a signed token
that they can give back to us
0:12
to prove they are who they said they are.
0:15
So, I think before we start on tokens,
0:18
I wanna make sure that I can
still get a list of courses.
0:20
So let's run the app.
0:23
Okay, cool.
0:26
And if I come over here, and
I do a get on, users won't work.
0:29
So we'll do one on courses.
0:35
Send that, we get no courses, of course.
0:39
Let's try to post one.
0:42
Let's dump all of these.
0:48
We'll send the new one here,
we'll say that title
0:50
is Django Basics and we'll say the URL is
0:55
https://teamtreehouse.com/library/django--
basics.
0:59
Can you tell which things I
know the location of the best?
1:05
All right so let's try to post that.
1:10
And we get back nothing, right?
1:14
It didn't actually work.
1:17
It didn't go anywhere.
1:19
We get back to 200 okay.
1:21
Which is kind of funny.
1:22
That we get back to 200 okay.
1:23
It should not have done anything.
1:25
If I was to do a get on this.
1:27
I should see nothing.
1:29
Okay.
1:30
So what if we go ahead and
send it through some auth.
1:32
So let's do basic auth.
1:36
User name is Kenneth Love.
1:38
Password is password like we
said before and I'll send that.
1:40
And now notice I get back actual data,
so that's pretty cool.
1:44
I don't get this unauthorized thing.
1:48
But it didn't let me do anything.
1:50
Nothing came through.
1:52
For doing tokens you might be
expecting that we need to install
1:53
another package and all this stuff.
1:57
But we actually don't need one.
1:59
Flask has a dependency
called it's dangerous.
2:01
Which does all of the token work for me.
2:03
These tokens are actually
known as JSON web tokens.
2:05
I'm gonna link to a really great
breakdown of them in the teacher's notes.
2:08
And also of course the docs for
it's dangerous.
2:11
Before I generate the tokens, though,
I want to set up the token auth.
2:14
So I'm gonna add all of that into auth.py.
2:18
We've gotta add two more imports here.
2:21
We're gonna import HTTPTokenAuth,
and we're going to import MultiAuth.
2:24
So just like with basic_auth,
we're gonna do token_auth = HTTPTokenAuth.
2:29
And I'm gonna to enter a scheme here
that's going to be called token.
2:36
Schemes are kind of like domains, areas
where a thing is appropriate or applies.
2:40
When we're doing this basic auth,
if you were to look at, sorry not there,
2:46
headers you would see this
authorization thing here has the basic.
2:52
That's the realm or the scheme is basic.
2:57
So for us we're going to call it token.
2:59
And then we're going to make
instead of basic auth here,
3:02
we're going to do multi auth.
3:05
And we're going to this is made
up of token_auth and basic_auth.
3:07
Kind of the reverse of the location
thing for the APIs MultiAuth looks
3:11
at the first thing first so it tries token_auth
first and then it tries basic_auth.
3:17
And if you don't want to use token
you can leave this blank and
3:22
I do believe it defaults to bearer and
then there's others you can set that,
3:24
maybe a certain client expects
a certain thing, okay.
3:29
So when I have both types of auth
I want to have that all set up.
3:32
Now I do you have to tell the token_auth
3:35
how to verify a token just like I had to
tell basic off how to verify password.
3:38
So let me write that function real quick.
3:43
So, token_auth.verify_token,
3:46
verify_token, and we're gonna get a token.
3:51
So user = models.User.verify_auth_token,
and we're gonna pass in the token.
3:55
If user is not none, so
if we get back a user and
4:03
it's not none then g.user = user and
we gonna return True.
4:06
Otherwise we're gonna return False.
4:13
Sorry you probably thought that function
was going to be more interesting.
4:16
It is actually pretty interesting
though we have to go add this verify
4:20
auth token though to actually
make it interesting.
4:24
So let's hop over here to our models.py.
4:27
And this is where we're gonna
create this new method.
4:29
So first of all up here.
4:32
We have to add from it's dangerous.
4:34
And we're gonna import
a couple of things here.
4:37
We're gonna import
TimedJSONWebSignatureSerializer, and
4:38
we're going to call that Serializer,
because I do not want to type that.
4:43
And then we're also going to import
BadSignature, and SignatureExpired.
4:48
All right, so now inside of class
User which this is one of the more
4:56
interesting classes I think I've
ever built here here at Treehouse,
5:00
I'm gonna add another
static method down here.
5:04
And I'll add it above this one,
just so that static method,
5:07
set password, and verify password
can stay next to each other.
5:12
So, static method.
5:15
There is no underscore in that,
there we go.
5:18
And we're going to call
this verify_auth_token, and
5:20
we're gonna pass in the token.
5:23
So, serializer = Serializer(),
and this is where we need to
5:27
do config.SECRET_KEY, cuz remember
we got our SECRET_KEY over here.
5:32
And so we're going to try,
data equals serializer.loads(token) and,
5:39
with the exception of, SignatureExpired,
5:47
BadSignature.
5:52
We're gonna return None.
5:58
Otherwise user is equal to User.get.
6:01
User.id is equal to data['id'].
6:05
Cuz data's gonna have
a key in it named id.
6:08
And we're gonna return that user, and
6:10
remember like here we are returning this
user, and if we look over here this is
6:13
going to get a user so
that user ends up being right there.
6:18
Otherwise we are returning None,
because right here we return None.
6:22
That's why we check against None.
6:27
So now we actually need to make the token.
6:29
So this is pretty straight forward.
6:31
Thankfully I'm gonna
put this one down here,
6:34
because it has to deal
with a particular user.
6:37
So, we'll say generate_auth_token.
6:39
Self, and then when it should expire.
6:43
By default I'm gonna
set it to 3600 seconds.
6:45
So, one hour.
6:48
So, this one's a timed one, you can do
a non timed one or you can make your
6:50
expiration super huge, like it expires in
a month or a year or something like that.
6:53
So, serializer = Serializer(SECRET_KEY),
6:59
which should come from config, and
7:04
expires_in is equal to
this expires argument.
7:08
And we're going to return
serializer.dumps, and
7:14
we're gonna set the key of id to the id
of the user that this being called on.
7:17
So this is pretty similar
to the verification method,
7:24
just the inverse of it.
7:26
Or make a serializer instance
with the secret key.
7:27
I want the tokens to expire all that and
7:30
like I said I'll link to
the it's dangerous notes.
7:33
So you can see more
about these serializers.
7:35
Something else to point out is that if
you've used the JSON module before this
7:37
.loads and this .dump should be pretty
similar, it's actually load string and
7:42
dump string so,
very close to the JSON module.
7:46
Okay there's a lot to do and
7:50
I still don't have a way to
actually give a user her key.
7:53
So how we do that?
7:56
I'm actually gonna do
that over here in app.py.
7:57
I could do this on the user resource but
I kind of want to do this in here to
8:00
show you how to add end points that aren't
part of resources, but look like they are.
8:05
And also just because it feels kind of
odd doing this on the user resource.
8:10
All right, so I need to import g and
jsonify and then from auth import auth.
8:16
And then,
we're gonna to make a new route down here.
8:25
So app.route, api/v1/users/token,
8:29
methods equals, I'm only gonna
allow one method, which is GET.
8:36
And then this is also login_required.
8:41
And we're gonna get_auth_token and
we're gonna
8:44
say the token equals
g.user.generate_auth_token.
8:49
And we're gonna return
jsonify({'token': token.decode('ascii')}).
8:54
Cool.
9:03
So we have to generate
the token on the user.
9:04
And we're gonna send it
back as a JSON response.
9:09
Hence the JSONify.
9:11
We have to decode it into ascii first,
just to make it safe to send across.
9:12
Of course we want to make
this a login required.
9:18
Because we have to actually have
a user to give the token to.
9:20
All right.
9:23
So, I should already be
logged in from creating this.
9:25
So, I should be able to go to GET,
and users/token, hit send.
9:28
And there's my token.
9:37
So that's pretty cool.
9:39
And now I can grab this.
9:40
I can go over here to authorization,
say No Auth.
9:42
Go to headers, change this here to
token and paste in my key right there.
9:48
And now, I've got my token which is cool.
9:55
And my token didn't change,
9:58
if you notice my token stayed the same
here when I requested that again.
10:00
Iām still authenticated.
10:03
I'm all set up and
Iām ready to do a lot more stuff.
10:05
If you give them a token
that doesn't timeout,
10:09
you could provide them a key when
they register their account.
10:12
Then they can just send that back
every time as their authentication.
10:14
This eliminates all of
the password submitting,
10:18
other than when they sign up for
the first time.
10:20
But makes your token a little
less secure because someone
10:22
else could get a valid token and
be able to make submissions forever.
10:25
Weigh the pros and cons yourself and
10:29
pick whatever you think is the better
solution for your particular project.
10:31
You need to sign up for Treehouse in order to download course files.
Sign upYou need to sign up for Treehouse in order to set up Workspace
Sign up