 Thank you so much for being here, for listening. I'm going to be talking about REST APIs here, and specifically, security of REST APIs and kind of even more specifically, authorization, authentication within your REST API. So hopefully that's what you're all interested in. There's going to be a little bit of knowledge of Django REST framework that's going to be helpful, but hopefully if you haven't gotten a chance to play with it, I'll give you a very quick primer that hopefully will kind of get you started there. So what are we going to go through today? We're going to talk about why REST. Why is this important right now? Why are REST APIs a big deal? Why am I talking about them? And why have they changed a little bit in their scope and caused all of these, at least for me, security considerations? We're going to talk a little bit about what the state of REST is today. So if you're writing a Django app and you want a REST API, what do you do? And then we're going to get into security a little bit, quick overview of kind of the considerations around security, authorization, when you're doing a REST API. We're going to talk about some of the strategies that we've come up with to write clear, maintainable permission schemes for your API. And then we're going to talk a little bit about what I hope happens tomorrow. And I think our tooling is not quite there yet, and I want to talk about how we might be able to get it there so that we can write really clear, sane, easy API permissioning. All right, so let's get started. Why are we talking about REST? And the simple answer is all of these guys, Angular, Backbone, Ember, and so on, have just exploded in popularity in the last couple of years. And there's all this growth. They're really taking over a big chunk of what we do as web developers. And so the more nuanced answer there, then, is I want to talk a little bit about kind of the pieces of your app, what's running where and where these new JavaScript frameworks come into play, and how that changes the game a little bit. So you can break down your application into three basic components, very roughly. Display logic, which is happening traditionally on the browser. App logic, which is kind of what's running your app. And then data stores. And the traditional way that historically these have been broken out is the display logic happens on the front end or in the browser. Pretty straightforward. And then your application logic and the data stores and all that all lives on the server, the back end. And historically, we've used HTML, CSS, and JavaScript to talk to the browser. And then the browser posts some HTML form back to the server. And it all worked really well until we wanted to do more things in the browser. And we came up with this Ajax thing, and we sort of shoehorned it in there. And that worked fairly well for a while. And things grew and grew. And we started doing more and more of the application logic on the front end, in the browser. And this is really with Angular and Backbone and so on. That's where this really kind of came into its own, is huge portions of what your app logic, which traditionally lived on a server, is now happening in the browser. And it turned out that app logic needed to sit a little closer to your data. And so we came up with, or it had been around for a little while, but we started using REST really heavily to shuttle that information back and forth at a lower level between the front end and the back end because you're doing all of this app logic in the front end. So let's start talking about how we do that today, the state of REST today. This is just Google Trends, which is, you know, take it for what it is. But the blue line there is Django REST framework. The other two lines are Piston and TastyPie. I think there's a couple of interesting things to note about this graph. One is Django REST framework seems to be the clear winner of this crew at this point. And it's really only happened in the last couple of years. You know, I think there's a huge community around this now. And, you know, there's a lot of tooling around it, which is great. The other thing to note about this graph is just the magnitude in general, right? All three combined, it's really exploded in the last year or two. So this is, you know, to me, this says this stuff's pretty important and growing in importance. So I want to give you a real brief overview of what Django REST framework gives to you, just so you get the ecosystem a little bit. There's serializers, which help you translate your Django models, your data, into a representation to be sent down over the wire, so JSON, XML, that sort of thing, and to be reinflated on the way back. There's views, which kind of connect up the query set, so your data, with that serializer, and then you connect that to an endpoint. You can serve, in this case, cats at a given URL for your API. It comes with a bunch of authentication stuff. So it comes with a bunch of built-in ones. They're, it's pluggable, so you can down, you know, you can pip install some other ones. But there's a really, you know, pretty straightforward framework for adding authentication into your API, and then permissioning. And we'll dive a little bit deeper into those, too, the rest of this talk. Cool, so let's talk about security, authorization, authentication, in the context of this REST API. So you remember this diagram, where the front end, the browser, was swallowing up your app logic. There's another important way to think about this, I think, which is a lot of your app logic is now running in this insecure browser environment, right? If you think about it, we've been able to rely on the server being, you know, presumably secure, right? That code there, you know you wrote it. You know what's running. The browser, not so much, right? The browser, anyone can do anything. A nefarious agent can, you know, mess with whatever they want. And as soon as we started doing more of the app logic in the browser, and getting closer to the data store, it opened up a lot of new security issues that I think that we, you know, we don't have a lot of practice working with as web developers working in Jango more, you know, historically the way Jango's worked. So there's new concepts to sort of wrap your head around here and some new security issues to be aware of. All right, so I want to go quick overview of the kinds of authentication. Just to give you a sense of, like, what's involved here, right? Why is this such a big problem? It's sort of an n squared n cubed problem because there's so much going on. Authentication, right? There's a lot of different ways to authenticate. Many of these are built in. Some of them you can, you can pip install. Like I mentioned, you've got HTTP basic auth, Jango session auth, token auth, OAuth, JSON web token auth. There's a lot of different mechanisms that you can install to do authentication. And the key here is probably most of these web apps are not using just one, right? So, you know, you might use Jango session auth as kind of your main authentication format. But then also if you're going to do a password reset, there's a token there and that's a different kind of authentication. And maybe you want users to sign up with Facebook and then that's another kind of authentication. And suddenly you've got all of these different levels of authentication that you have to deal with and cross-reference with all the different kinds of permissions that you care about, right? And there's a lot of these as well. So, you can have table level permissions, right? Can you access the cats or not? There's row level permissions, right? Is this your cat or is this someone else's cat? And what does that mean for your permissions? There's column level permissions. So, as much as we love cats, let's talk about, you know, the user model, right? You might want your users to be able to set their name, right? Change their name in your website. But you probably don't want them to be able to set the super user flag, right? And so suddenly you've got these column level permissions where you have to say, these kinds of users with these kinds of authentications should be able to touch these columns, not these columns. And then HTTP verb permissions, which roughly analogous to read, write, and that sort of thing, read, write, delete. You know, and so, you know, like I was saying, all of these things combine and you start to get this n squared or n cubed problem because there are other factors you need to take into account where there are a lot of different combinations, a lot of different situations that you need to account for. And it gets messy really, really quickly if you're not careful. So, let's talk a little bit about how we do a good job of this today, right? What tools do we have at our disposal today to, you know, put some order into this and make it maintainable, make it sane? So the first and really the biggest concept that I want you all to understand and take back and implement is small composable permissions. Take those permission classes in Django REST framework and make them as small and focused as possible. And you'll see later we're going to use, we're going to use a tool to kind of compose those into more complicated permissions. So, you might have some HTTP verb permissions, right? So we can create one called isPost, subclass the permission class, and then hasPermission, this function that says, you know, does this person have this permission, really just checks, is this a post? And that's it, right? On its own, pretty much useless probably, but when we start composing it with other things, you'll see the power of this. And then so you might have one for isPatch, you might have one for all the HTTP verbs, right, and then these become tools in your tool chest that you can apply to more complex permissioning problems. Let's look at user status. You might have an isAuthenticated permission, right? And this one that has permission just checks, are you authenticated? There you go, simple, easy to unit test, easy to think about, easy to reason about, and they'll come together in really powerful ways a little later. You might have one for isSuperUser that checks the SuperUser flag. And then, you know, all the other authentication methods, right? So you'd go on and on and on. So, you know, if you have Facebook authentication, you'd have some of these for Facebook. If you have that URL token as an authenticator, you'd have one of these for that, right? Just really simple checks. You're going to do the same thing potentially for ownership, right? Are you the owner of this cat? And there's a little bit of a caveat here, the way that Django REST framework is set up, it's really hard to do this check in the hasPermission like you would want, right? So for list level permissions, getting a bunch of cats, for example, you really end up having to implement that in the getQuerySet method on the view, on the view set, which is one of the things that we're going to talk about hopefully making better in the future. But then you see the hasObject permission, which where you can kind of define, does this user have permission to touch this object, is pretty straightforward, right? Is this request user the owner of this cat object? There you go. And again, you'll do this for all of the different components in your application that you care about. All right, so to put it all together, we need a couple more power tools. The first is a field restriction helper, and I'll walk you through this. But basically what we want out of this is, remember I mentioned, if you want your users to be able to set their name on their account, but you don't want them to be able to set the super user flag, this is how we're going to accomplish that sort of thing. We're going to, it's basically, it ends up being a class constructor or a class factory. I've capitalized this to make it look like a class, I think that looks nice in the final product, but technically this is a function, if that bugs you when you do this, you can go ahead and name it lowercase. But yeah, so you're going to have a function that takes a set of fields, right? So like the name field, but not the super user field. And what it's gonna do is it's going to construct that permission class for you on demand. It's going to create a set out of the fields and save that for later. And then that permission class, when it gets asked, does the user have permission? It's just gonna say, hey, all the fields that you're talking about in this request, are they a strict subset of the allowable fields that this was created with, right? So you can say, if you pass in, you do an is fields and you pass in just the name field, then anyone who ever tries to touch the super user flag will get denied by this permission, right? And you do essentially the same thing under the has object permission. And then you return the permission class. Awesome, so now we can restrict the columns that you're accessing. This is a tool that, as you can see, this is a basic version of it. It's relatively straightforward to put together yourself, but it's also something that we've written and we'd like to open source, so hopefully we can do that soon for you guys. We'd love more batteries to be just out there and ready to use. So the last power tool we need is this thing called REST condition. So you can pip install REST condition. And this is really the crux of everything, right? It gives you these composers, these ands and ors and nots that you use to put these pieces together into more complicated permissions, right? So you could combine two things with an or and you could describe a permission as if you have foo perm and not bar perm, or if you have baz perm, then you have this permission, right? And so let me show you an example of how we build a relatively complex permission structure out of these tiny pieces and this REST condition stuff. So we've got a view set here, right? We're gonna view some cats. It's gonna have a lot of other stuff. If you've written Django REST framework stuff, this will have, you know, this view set will have lots of other things defined in it, but what we care about is this permission classes where we're defining it at a base as this or. And this is a pattern that you'll end up repeating again and again. The base is just oring together a bunch of different sets of permissions. You know, different kinds of people have different kinds of access and that's what you're describing here. So for example, this first one is if it's a get, head or option, so effectively read only, and you're an authenticated user, great, you're good to go. Or if it's a post or a patch and you're the owner of the cat and you're only touching the hair or grumpiness level, then you're good to go. Or if you're a super user, you can just do whatever you want, right? And so you can see this is, you know, it's not totally short, it's not totally easy, but it's a lot less messy and a lot less complicated than the alternative, which is writing all of those things again and again for every view set, right? For every set of permissions. So these kinds of composable things, and you know, it makes it much more readable, much more maintainable, to have these things as kind of composable base permission classes. All right, so let's talk a little bit about the world of tomorrow, right? How can the world be better if we were to build some tooling around this? So let's first give a quick overview of kind of the problems that exist here. So there are a few things that I think still plague us, even with these kind of small composable permissions. One is everything's endpoint based, right? We defined this on the view set class, right? Which roughly analogous to an endpoint, the cat's endpoint of your API, right? I think the easier way to reason about this stuff is to have it be role-based, right? Role-based permissions. So if you are a super user, here's your list of permissions. If you're a cat owner, here's your list of permissions. And then those all get combined, but they get defined at a role-based level, right? Much easier to reason about. Another thing that plagues us is this code is still scattered, right? You saw we've got, has permission, we've got has object permission. Some of it had to go in get query set, and it's still scattered throughout every single view set definition, all of those little composable permissions. It's in lots of different places. And centralizing all of the permission code in one common place, I think would help a lot in kind of reasoning about it, right? It's all the right there. As I mentioned, batteries aren't entirely included here. A lot of the authentication schemes are. But that is field thing. There are a lot of other pieces of this that we've had to write internally. We're working to open source those, but in the meantime, right? These batteries are not really included. And the default is confusing, right? Do you default have permission or not have permission, right? The more secure option is default, no. You don't have permission. But the way this is working, it's sort of confused. In some ways it's one, in some ways it's the other. And I think it'd be helpful to just standardize. No one has any permissions unless you explicitly say so, right? So I wanna tease, imagine what this might look like. This is a, none of this code has been written underneath the, none of the code that would actually run this has been written, but I wanna give an example of maybe what this might look like, right? Just to kind of tease the idea. And hopefully if anyone here is interested in this, I'm gonna be spending the rest of the week hacking on this and trying to get something together. If you're interested in helping out, I'd love your help. I'd love to make this a better situation for everybody. But this is sort of a V1 idea of what the world could look like, right? You're defining a role-based permission. So anonymous user here, right? You're telling me is it active, right? For this request, is this role active? And then you just define the permissions there, right? So in this case for the cat endpoint, you can list or retrieve, but because it's default, no permissions, you can't post, you can't patch, you can't delete, right? And this would go on, of course, for other permissions and you'd go on and define other roles as well. So there's a lot of nuance that isn't included here. There's a lot that still needs to be figured out and kind of the way this would be implemented. But I think making this whole ecosystem a lot easier to reason about, easier to maintain is gonna plug up some serious security holes. I know, even with these composable permissions, we've had security polls and I wanna save people from that. I think that's partly our fault, right? We wrote the code, but partly the fault of the tools. The tools weren't helping us write secure code. So that's what I want for us. And like I said, if you are interested in helping, come find me. So thanks so much, I'm Jeff. I have to give a quick plug to choose because they paid for me to be here. So if you know anyone in San Francisco who wants better lunches at work, let us know. And yeah, that's it. Thanks so much.