Submind YouTube summaries
Thumbnail for Sam Scott: Authorization and SQLAlchemy - Montréal-Python 83 – Minimum Night

Sam Scott: Authorization and SQLAlchemy - Montréal-Python 83 – Minimum Night

Watch on YouTube

Video summary

Sam Scott, co-founder and CTO of OSO, introduces authorization as a critical component for securing applications, distinguishing it clearly from authentication. While authentication identifies who a user is, such as logging in with credentials on GitHub, authorization determines what that specific identity can do within an application. He illustrates this by showing how different permissions apply to various resources, like viewing teams in one organization versus being restricted in another. Scott argues that handling these permissions often leads to messy, unstructured code filled with complex if-else statements, which are difficult to maintain. To solve this, he advocates for a structured approach using roles, a concept abbreviated as RBAC or Base Access Control, where users are grouped into buckets like members or admins, each with predefined capabilities that simplify the logic of what actions are permitted. To implement such a system effectively, Scott presents OSO, an open-source authorization library designed specifically for developers to integrate security directly into their applications. The core of OSO is a versatile library available in multiple programming languages including Python, Node.js, and Rust, which serves as the foundation for making authorization decisions. He highlights two additional key components: built-in functionality for managing roles out of the box and a declarative policy language called Polar. This language allows developers to define rules that express exactly who can perform what actions on specific application objects, such as allowing a user to read an organization if they are listed as a member. By separating these policies from the business logic, OSO enables a cleaner separation of concerns where security rules are defined independently and enforced programmatically. The presentation culminates in a live demonstration integrating OSO with SQLAlchemy, a popular toolkit for handling SQL data models. Scott walks through building a simple API that initially allows unrestricted access before implementing authorization checks to restrict users based on their email domain. He then evolves this example by introducing the built-in role management features of OSO, which automatically handle database lookups to determine if a user holds a specific role within an organization. This approach eliminates the need for hard-coded conditions and allows policies to be written generically, such as granting read access to any user who possesses a valid role in an organization. Scott emphasizes that this integration is highly efficient because the enforcement happens at the database layer, ensuring robust security without bloating the application code with complex permission logic. In conclusion, Scott positions OSO as a solution that bridges the gap between simple, easy-to-use frameworks and powerful, extensible systems. He addresses common questions regarding integration with JWT tokens containing scopes and compatibility with FastAPI, explaining how OSO can handle scoped tokens by combining user identity with token permissions in policy definitions. His argument is that while many frameworks excel at basic authorization, they often fail to support complex or evolving use cases without significant friction. OSO aims to provide the best of both worlds by offering immediate simplicity for standard roles while retaining the flexibility of its underlying policy language for advanced scenarios. Ultimately, he encourages developers to leverage these tools to build secure applications that are easy to maintain and capable of adapting to changing security requirements as their projects grow.
Read the full video transcript
okay so yeah i'm sam the co-founder and cto at oso um i'm gonna talk about authorization which is one of the main things we're solving here at also uh so i'm just gonna give people a quick outline of what is authentication and authorization how to release your application uh i'm gonna talk through some very common patterns around roles and do a little live demo for this instinct like you know so i'm going to keep trying to go through things reasonably fast okay so authentication is this process of identifying who you are so you know you go to github for example you log in with username and password and you sign in as in my case samsung89 this is authentication github now knows i'm sam um and the next question is you know what can sam do and so this is authorization right so suppose i try and visit these two urls um you know one for the oso org teams one for sql alchemy teams i see these two different pages and basically what's happening here is that github has decided oh samsung89 you're a member of the ursa organization you can see the teams but as it says here at the bottom i'm not a member of any teams in this equal alchemy organization so it's not allowed all right this process here is authorization and this is what i'm going to be talking about today now authorization is kind of this somewhat you know vague unstructured problem you know who can do what in your application and it's very easy to end up with code that looks something like this where you have a sort of kind of if else statements you're checking a bunch of different conditions because often this is what permissions come down to you know it's like who can do what and you define this by you know check universe various properties so what can we do better than this like how can we how can we make our application structured nicer so it's easier to maintain update change things like that so roles is this very very common approach to this now what roles does is it takes your setup like this so suppose you have you know a bunch of users you have a bunch of resources things that try and access and it helps you break this problem down um but you know i should say you often see this abbreviated as our back which stands for base access control again so what this what roles do is they take this problem and they basically say all right well most of these users you know maybe they fall into this bucket we call them members and there are only a few people who are you know privileged users we'll call them admins and now instead of having to define what everybody can do my app i just need to define what these two people can do members can read and write and admins can additionally delete kind of simple as that and again like looking at this in like a realistic example um here is a kind of a slice from git lab's permission system and so you see along the top here they have five different roles from the guest to developer to owner and there's like this table of all the things they can do right so this is a pretty pretty decent role system and you know gitlab is this huge huge application there's a ton of stuff you can do from maintaining source code all the way down to like managing kubernetes and deployment stuff like that so there's a lot of things you can do in it but they've managed to reduce it to effectively these like five different roles and the nice thing about these roles is they kind of give you this intuitive sense of what you should be able to do right like you wouldn't expect that a guest to your organization could come and start deleting projects or things like that whereas the developer you know can probably you know manage the code they can make edits things like that owners can you know do everything okay so this is like a nice example of um you know rolls down quite well because there's like a relatively small number of of them um and they kind of relate to intuitive concepts so um what i want to talk about around oso is how it kind of helps you to build this kind of a system so oso is an open source authorization system and it's designed specifically for developers building security into their apps um the kind of core of oso is a library and this is a library for making these authorization decisions so once you're deciding who can do what in your app and enforcing that and doing and adding this to your application and it's available through you know standard package managers so in the case of python know pip install oso but it's also available for a number of different languages the core of those is actually written in rust and we make it available to multiple different languages so node java ruby python go rust second piece is we we made also sort of batteries included and what i mean by that is we've kind of given you out of the box functionality to manage things like roles in your application and that's what i'm going to be showing you in the demo is how we've enabled this in sql alchemy um to allow you to do like a very rich like roles based access control system in your app with c glaring also and the final piece of oso is effectively how you configure it and you do this through the policy language called polar and it looks like this at the top so this allows you to express who can do what in your app in terms of um and by writing these rules so this rule here for example says that a user is allowed to read an organization if the user is in the organization organization members and this policy here it's written in the polar language which is declarative policy language but it's express over your application objects so when i actually call this at the bottom in the python library for example i call the oso is allowed function and i pass in my user object my organization object from my application data so this policy at the top here is expressed over attributes or methods or types things like that from the application so for those of you who are familiar with sql alchemy um you know it's this sort of it's this large amazing toolkit for you know handling all kinds of sql inside your application so you can you know managing everything from you know writing sql queries and expressions it's got like an rm model so you can use python classes to represent your data your data models migration tools and kind of on and on it's kind of this entire toolkit for everything sql in your app um oso kind of wants to be the same for authorization and so the pieces i've spoken to about today is is sort of just the starting point um and kind of in this way these two provide this uh this like really great match together where they sort of both giving you a lot of this out of the box kind of experience and things you need to think about for how to do sql authorization and we'll see together how those kind of pair up nicely okay cool so i'm going to give a little demo of the sql archiving oso integration what i'm going to start with i have a very very simple github api built with a combination of flask and sql alchemy which i'll walk through uh we're going to start off just by adding some simple authorization with oso so just want to kind of get the basics in and then show you what it would look like using our built-in stuff for roles um so we can kind of create something similar to what i was speaking about earlier okay so here is my application let me make this a bit bigger for you uh here's my my data models so this is where i'm using the sql alchemy data models to define my data sets so this is very very straightforward i have a user class you know has an email address for example i have organizations i have repositories right so this is my my github very simple github data model and your repositories can belong to an organization for example then in my my root.pi files this is where i'm you know my flask uh api endpoints i mean i'm using uh i have some some simple routes to allow me to do things like list all the repositories in an organization so for example if i go and get the if so i'm going to hit the api using curl if i call this api as the userportbeatles.com and get the repost for organization one uh you can see this the organization has one repo called abbey road whereas organization two has one repo called paperwork okay so right now every user can do everything so what if i actually wanted to restrict what paul the beatles was allowed to see and say that he could only actually see repositories from organization one so what i want to do is add in some authorization here in my repos index to check that you know the user can actually read this this organization so first of all i'm just going to get the current app uh helper from flask allows me to get application state and i'm going to get the i'm going to get the oso object off of my application state so where's this coming from what is this so the way i initialize oso is in this in my flask initialization um you see i have a method on my app that i'm going to call on startup which is just going to create a new oso instance um and do some do some relevant things like load my policy files in as i said that's how i configure my app my my authorization is through policies and finally i'm going to add ozone to the application state okay so that's where that's coming from i can now get my oso instance and do authorization so i'm going to use the the flask the flask also helper method authorize which will take in the organization it's automatically going to populate the current user and but i'm going to say the action i want to check is a read action okay so once i've added this line i'm now doing authorization as part of this api endpoint if i now go and try and access an organization i'm getting 403 forbiddens nothing is allowed anymore because um basically once i configure oso it's 9 by default and my policy is currently completely empty i have no i've no policies i haven't allowed anyone to do anything so everything is is not allowed let's change that let's let's allow everything let's allow every user to every action to every resource um and i can do that by writing it this way these are basically my my inputs my input variables and i can just i don't need to add a if statement i can just say this is always true so now i've done that i am now able to access everything again okay so we're making some progress we have authorization we've allowed everything uh let's let's let's restrict that a little bit more so like i said earlier these inputs are coming straight from the application so this user is a user the action we're checking is reeves and this is actually an organization and so we want to say maybe we just want to say that the user's email address must end with um beatles.com let's say and the organization name is of organization number one is actually the beatles there we go so now we have a policy saying that only users with the beatles.com email address can read the beatles organization so i can still not access organization 2 but i can access organization number one which is the beatles org so cool i've got some i've got some authorization going on but clearly i don't have to do this for every single user in my system every single organization that joins i want this logic to be like generic over over organizations more generally and so that's where roles come come back into the pictures i basically want to express this the fact that users can have a relationship with organizations and that relationship is is effectively their role so let me reset this okay so i just checked out a new branch which has my roles implementation and i'm actually going to reset that so i can show you the the diff there we go okay so you can see the changes i've made um right here i need to make that a little bit smaller so in my in my initialization page um i'm just importing this new built-in rolls functionality and enabling that on the oso instance so that's all that happens and really the magic that's happening here is i'm importing this resource role class helper from the sql alchemy oso roles package and what that's going to give me is give me this sort of helper method that allows me to find a mix in to create a roles relationship between users and organizations so here we can see it let me hide this so here we see we're creating the mix in by calling this ho this helper method from oso giving in the user of the user class the organization class and the list of roles we want to create on that you know between those two things and now i have this mixed in i basically can create a new sql alchemy model so this is creating a new database model um but basically pre-filling a lot of information from this this oso helper mix in and now that this is in place i now have a data model connecting users and organizations and actually there's a bunch of helper policies now already added to my app so i can now start doing authorization directly over users that have roles in my app so suppose i added some data just like this to say for example that john is an owner of the beatles org then in my my policy might look something like this and let's go back to the regular screen here we go so instead of writing my allow rules like i did before i can now write these role allows which really have the same purpose but is effectively handling all the like um the the database lookup you know the is is a person in a particular role or not like does this exist in the database and those kinds of things i can just focus on writing permissions in my uh in my in my system so like this one says that if you have any role inside an organization then you have read access to that organization um so in my in my root now you in my repos index root you can see that i've updated the action to list repos so i'm going to check whether the current user is allowed to list repos for this organization and if i now come back okay cool so you can see paul is now still able to list uh repost from organization one and not from organization two but whereas before we kind of like hard-coded the beatles.com and the and the old one thing this is now true over um all users and all members who have who have roles so for example i have sally monsters.com who cannot read organization one but can indeed read organization number two because of the role they have and um and yeah so this you know this is really all that all that we need to write in here is just some simple policies about what and roles do everything else is taken care of in the database models and i think the really nice thing about this is um just how few lines of code we needed to get that role model set up this is now extremely extensible it can support everything from like inheritance patterns hierarchies it can do um you know things like you could even have a role for a repository if you have the role in the parent organization things like this and with the oso sql alchemy integration this is actually all enforced at the database layer itself so this is incredibly um efficient because it's actually all happening just over the database and not like in the in the python code okay so those are the main things i wanted to cover um this was a pretty kind of quick intro to oso and the sql alchemy stuff in particular we have a lot more information available on our website on our doc site um or you can come speak to us directly for example in our in our slack channel we have for the open source community or see things on github and specifically if this if this example is interesting i'd recommend on the docs page which you have that sql alchemy example is like a tutorial okay thank you very much for listening thank you so much that was super interesting and thanks for sharing the links to where to reach you and get some more information on my side i didn't receive any questions for your talk for now so thanks all right hey yeah thank you sam for for your talk uh i i i'm i don't know i don't have a lot of uh of experience with uh authorization and all of that thing but uh uh can you give us a bit uh the com comparison about uh also and and maybe the other system that already exists why also it's uh like more cool [Laughter] so i think the the thing that i think really sets oso apart is that we're sort of going for the we're trying to we're trying to kind of have the best of both worlds in that it is very easy to do the sort of simple things and you know roles can get roads can get complex but like when you start out and you just need to say a user and an admin you have two roles maybe just hard code them it's fine it can start out easily but like over time it gets hard um and so what we're really trying to do is make the easy stuff easy by providing that out of the box two lines of code you're good to go you have roles but because it's you know backed by this policy language the policy language itself is like very powerful um and can be used for more things than just authorization for example this actually means it's like very extensible so as your crimes change if you have some weird use case it's not quite a role it's like somewhere between the two it's fine the policy language will let you write those i think like a lot of frameworks they maybe do the simple stuff very well but they don't let you extend and then you get into this like very hard um situation where you're trying to like fight against the system thank you sam i actually got two questions as you were answering this one so the first one is how does it incorporate with jwt containing scopes and the second one is how does it work with fast api okay so the so on the one about jwts so for people aren't familiar with is these are sort of um authentication credentials so you get like a cryptographic token that maybe can include extra information for example a scope is like a typical one that you know the the github api contains for example so you might create a api key that's given a specific scope that says you know this token allows the the holder to read repositories that kind of thing so how that looks in oso is you would um you basically use it as additional information on the input user type so maybe in this case the uh you may need to look at a combination of two things so the user might be the person who originally created the api token but maybe the token itself is um kind of limited to only fewer things right so i've created an api token for github um so it can do things as soundscape89 but i don't want to do everything i want to just be able to read repositories so it has that scope so then your policy can contain both like what can sound do what can the token do make sure that both are applicable uh so hopefully that answers that question on uh fast api um it works pretty well with with fast api i think there's like a lot um because fast api has like a very strong preference towards a strong typing i think that works very well with the kind of types that you can use inside a inside the the polar policy um and we do have a we have someone who who actually from our community who wrote a fast api example app with with oso and it it fit really nicely it was a good combination don't have the link to hands um but it's if you you could either join our slack or email me and i can i can share it with you okay