RESTful and HTTP APIs in Pyramid Transcripts
Chapter: Authenticated services
Lecture: Isolating the API auth features
Login or
purchase this course
to watch this video and the rest of the course contents.
0:01
As we saw, having all this header parsing, database querying, API at the beginning of every one of our functions is super bad,
0:09
now we could slightly improve this by putting this into a function, right, we could come over here and say extract a method
0:16
and if I grab the right stuff and it didn't really like these return values I could store those values and check it, whatever, right,
0:23
I could make this work no problem. But, we can do better than this, so let's go add a new section of our web app here
0:30
let's go to infrastructure and over in this section, we'll probably end up with a number of other things
0:36
but for now, let's just put a thing we're going to call auth. And that method that we wrote, let's say def parse_api_key,
0:45
so let's break this into two things, request okay, so let's go over here and cut this out for a minute,
0:55
so what do we have, we have auth header, again, spelling matters, so we are going to get the authorization, if not this, we're going to return,
1:03
let's make a copy really quick of this, so we're going to return none, no auth header.
1:11
Actually, I am wondering if we should maybe pass the error message back as well, so let's go over here and say none and error is no auth header.
1:21
Let's go over here and say none, and the reason is invalid here got to import this, this is going to be none and the reason is invalid auth key,
1:32
and then finally, here we're going to return a user,no error so we're going to say given request let's go find the API key here,
1:42
so it has to live in authorization thing, there's none of that obviously we have no user and the error is this, if it's invalid, no user error is this.
1:52
No user, no user and the error is this, otherwise, we found these and there are no errors, so that's how we're going to use this little bit here.
2:00
Now, we don't really need this anymore, the next thing I want to do is I would like to be able to go over here
2:05
and just go something like this, at require auth, API auth, okay. So what we're going to do is build a decorator,
2:15
just a basic decorator that we can wrap on this and it's going to intercept the call here, and it won't even let it get to it,
2:21
if there's no authorization, right, it's going to manage all the stuff that you saw us do, and we go back here and turn this back off,
2:28
because we're not going to need this anymore, instead we're going to have this So, how do we do that? Let's start really simple,
2:36
so decorators are just functions, okay, and decorators are just functions that take a function,
2:41
what function are they going to take, the thing that you put them before
2:44
so in our example here, if I say at this, let's be a little more explicit up here, so let's say this, [typing code] import that as auth, okay,
3:02
so let's make it kind of explicit where it's coming from @ auth.require.api_auth, okay, so it's going to take this function
3:10
and that is a function that takes one thing, a request and it returns a response, so we need to tell this thing to return a function
3:18
which takes a request and returns a response, right, so I am going to come down here and we'll have a def wrapped takes a request
3:28
and it returns some kind of response, and often this will just be by delegating to this inner function,
3:36
this wrapped function here, I am going to need to return wrapped, without calling it, now let's just do a print, before the wrapped func
3:46
and let's go ahead and try to print it here maybe it will tell us what it is func ; okay, so do we have it over here, we do, and restart,
3:57
before the wrap function and here are all autos at this address perfect, now did it work, did it still run— it did, look, down here at the bottom,
4:05
we've got all this stuff, and that part happened right here, this is the actual execution of that API call.
4:15
So this before part came before, then right, here's where we can do that validation so we'll say user error equals parse api key with this request,
4:28
and we'll say if error then return response from pyramid with a status just like before, 403, and the body being the error, like so.
4:45
Now, maybe this car, remember what we had up here is we had a little print statement, print listing cars for
4:54
we give a name here, we said . format( user.name) what is the user, what if we actually need to provide the user,
5:01
not just make sure they can call it or don't call it, so we can do that step right here, before we call the function
5:08
but we have already verified there is a user, we can say request.api_user = user.
5:15
Now, we could plug into the pyramid all stuff and try to make that user but I kind of feel like just making it super explicit like this is the user;
5:24
So let's go over here, you can choose to do that however you want request.api_user.name and this has to be
5:33
again put back request now that we want to use it an the idea is, if this lets the function run there will be a user,
5:40
if there's no user, this function doesn't run, so you don't need to worry about whether or not this is there,
5:45
right, it's going to be there; now let's try this again, this should be awesome, are you ready?
5:50
I'm over here, who is our user, this is the authorization I believe I got it for jeff and first of all, let's not send it, see what happens,
5:56
boom 403 forbidden no auth header, so you could say like maybe a nicer message, like you must specify an authorization header, something like this,
6:12
but whatever the error is, there is no auth header, now if I pass it in, and maybe I get this wrong
6:18
I'll put an extra f on the end, first of all let's mess this up make the api thing wrong, so it's invalid,
6:24
make it valid, now it's valid but the value corresponds to no user, there's no user with that account, take the f off,
6:30
now, so notice, none of this crashed, right, this was never run at all, because the outer shell was guarding it, right
6:42
this required auth API that we created is guarding it now it should pass through that, and on the way through
6:48
it should set the API user to jeff, let's try— boom, so it works fine over in our log files, well ''log files'', in our print
6:57
we have listing cars for jeff, what do you guys think, is that killer or what? So just to review, we come over here, we wrote two functions
7:05
one that knows how to suck this authorization header apart, break it into its pieces and give us the API key,
7:10
and then there's a very very simple decorator that takes basically right here what turns out to be the thing that gets executed,
7:17
wrapping around the API call, it checks for the user and if there's no user, return error, don't ever call the function,
7:25
but if it is good, set the API user and call the function.