Flexible Authorization with Permissions, Policies & Roles in C# .NET 8

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
let's finish up the brand website authorization with Jason Taylor's flexible authorization project this work of art includes roles permissions and policies I will use the standard officially documented built-in.net 8 and Blazer authentication and authorization mechanisms since it's likely the most useful approach for you I'll make sure to publish both the standard approach and my adapted modular approach to my patreon my custom approach will only slightly deviate from the standard approach and those differences will only be in the Blazer front end but let's start where we left off in the last video which was authentication and Blazer and role-based authorization was also already possible I'll briefly talk about the shortcomings of role-based authorization and then go over into policy based authorization before I touch the flexible authorization which uses both I highly recommend to after this video of course check out the original GitHub repository of Jason Taylor and the Jason Taylor talks about the subject so what I want to achieve is something like patreon itself and it is a member section where you can have different levels of access but so similarly like roles but those roles or access levels are not set in stone they are not hard coded into the project you can add those and remove those and so on let's take a look at my patreon which is found on patreon slash I guess stupid and these special thanks for the already three members that are supporting the YouTube channel this means a lot to me and my family and motivates me to keep going and build even more and better projects for you so you see all of these posts and there are memberships that's in my native language sorry for that but you can easily add a level or a membership level and edit them remove them and so on this does not imply that the development team of patreon has to then dive into the code base and yeah change all of their conditional logic based on the levels I add and delete that's all quite Dynamic and flexible so if I would go to that same patreon page where you can find all of my work as a non-authenticated non-authorized user you would see so the membership and then most of the things are locked most of the things are free but you need to have a patreon account and then some things are exclusive to the member levels so that's basically what I want to achieve in my brand website as well I have specified the rules I want to have access to this content and in the nav menu I added some rules as well administrator and manager and I could keep going for every component I want to lock behind certain roles what happened here is the first thing I already mistyped so I accidentally put managers which wouldn't work also having to duplicate or specify all of the roles each time all over your code base is going to take quite some maintenance to update to to test and so on and what I find very unfortunate about this approach is we keep having to repeat all of the roles that have access instead of being able to imply that the administrator has all of the access so all of the moderator axes and the moderator might have all of the managerial access and the manager might have more access than the visitor so it would be easier to just specify a visitor and then have all of the access levels above also be able to access this you could achieve that with some custom code for example rolls with admin access only the admin rules with moderator access or the admin and the moderator rolls with company access or the admin D and then all of the rules that also have that access and you could specify some simple methods as admin access so only the admin users has moderator access so the users with the admin role and with the moderator role and so on you could also accomplish that by using the out of the box approach of.net by specifying policies and the add authorization so elevated rights for example requires multiple rules so administrator moderator manager whatever you say and that could then be maybe be named has manager access and then you could use those policies on the like specified above on the methods on the API endpoints but to also have these policies active on your Blazer front-end you'd have to specify so duplicate these into your front-end project and then you could simply instead of the rules you could use the policy and then use the name test manager access that is slightly better slightly more maintainable but it's still hard-coded all over the project so you'd still have to update these policies and redeploy your project and so on so instead of hard coding roles or policies and using those all over the project we're going to use permissions under the hood these will be dynamically generated policies these permissions on the left so view manage rules view manage users view manage permissions can then be given to the roles and after that the user with one of these roles can access that specific feature or functionality in your application you can make this as fine-grained as you want but typically these permissions are more tied to the feature and to the action that the user can take rather than some role which makes a lot of sense for this brand website since we have these feature modules since I can then specify that create blog post is another permission than viewing a blog post 30 blog post code will then contain checks on that permission so view or manage blog posts which makes more sense than administrator or moderator access or and I can then decide that one day the visitor can also edit the blog posts or take permissions away so that's way more flexible and I don't have to take out hard-coded roles role checks all over the code so let's see that in action let's say I add a test roll create and then the industrial came along and now I just have to trigger a re-render so I'm gonna do that you see the test role that we could see all or none manage users maybe few permissions so that's pretty cool so now a user with the test roll can manage the users view the permissions but maybe tomorrow I decide to change that and just say you can only view the users and none of the other things and it's simple as that I don't have to go into the code and change a lot of things I just have to manage it right here what does need to happen of course is that user with the test role needs to well their access token will likely contain that permission at that time current access token has to expire before that change and permission is active then I can easily take that role away again let's see I have to re-render so I can add roles delete rules update rules without having to change the code and the permissions will remain intact so that's pretty flexible pretty dynamic I had to seat those users and those roles into the database so let's take a look at that first in previous video roles were already supported and identity but I made another custom role entity which inherits from Identity role so the base the standard one and I added a few fields to know more about the creation of it and then this permissions but to use this rule we have to alter the identity DB context to have that custom user model custom role model and the string is basically the type of the primary key and then I added the cedar to see some users and rules so for roles that's our custom role entity instead of the identity role I added a few users so the admin the manager and the visitors and then which user with which role I had to add rules our custom rule and then of course I added in the migrations let's go back to that permissions property which has a type of permissions which is actually an enum enumeration with the flags and you see the permissions specified in here with the value with the power of 2 so 1 2 4 8 16 32. which could be seen as zero zero zero one zero zero one zero zero zero one zero zero and so on and then the all is the inverse of none so we're not going to use these permissions merely for representation we're going to actually calculate with these you can calculate so permission a plus c would be so you can do calculations and the outcome will be a unique value and that unique value represents a combination of permissions so you can have a lot of permissions and theirs will just be summed up into a single integer value which then represents all of the permissions you have so if you would console log these as string you would really see a b c d e as permissions so for us it would be few rows manage rules few users managed users and you can also output these as integers which will will use to store into the database and you can use bit operators to add permissions together or to subtract permissions so adding permissions would be with the logical or operator so adding permissions B to the user's permissions is with this pipe and equals removing permissions with this symbol the xor operator and you can use this and operator to get the difference in permissions so if these would result in zero then that would mean there is no overlap and permissions which means you're not authorized if there is overlap between the Acquired and the user's permissions then you are authorized that means the user has one or more of the permissions that are required under specified those required permissions you can simply use this pipe operator and say the required permissions are either A or B so if the user has any of these you are authorized so using the you could use that within the authorize attribute instead of the role name or the policy name and this is where the on the Fly policy generation comes in so with the prefix of permissions followed by the integer value of the actual permissions so A and B would be three so permissions 3 would then be the policy to protect an endpoint or a view so instead of the policy name has manager access or has a visitor access this will now be permission and then the sum well the integer representation of that permission or the integer representation of the sum of those permissions and then the user will get a claim with the value of also permissions and then the integer which represents either the permission or the sum of permissions that that user has so instead of using the user's roles or the role claims we're now using a custom claim with a permission policy value let's login with a visitor and then I see permissions 5. if I go to the admin page I can see the users I can see the rules but I cannot add a new rule and then the manage permissions we can also not see because we only have The View users and the view roles permissions the GitHub repository of Jace Taylor and then we're interested in the flexible alt so the permissions notebook was what I just showed you and now the flexible odds let's go in there and we see a shared folder server and client in my project that would mean the underscore shared the API and the Blazer front-end there's a lot in here so it's quite daunting to start with this project but that's why I'm making the video of course I'm going to start with the server on the program CS and then you see yeah some database stuff and then you see some more so we saw that at rules we see a claims principle Factory which we'll see later then we see some stuff for identity server which we can ignore since we're not using that can also ignore that partly we'll have to add authentication to our Blazer pre-render server unfortunately and add the bearer token authentication and we're only interested in these two lines the eye authorization Handler permission Handler and the flexible provide policy provider and that will likely live in the shared project since in the front-end project you'll also need to register these and let's start with the API so we have the yeah we have the extensions CS in our authentication module since this is a class Library and that's where I added these handlers and providers and I also added this claims principle Factory but let's look at this one first and this inherits from the authorization Handler with the permission authorization requirement this one is basically just a collection of data parameters data policy can then use to evaluate on so let's say this was a requirement to check the the age of a user so the minimum required age then this would just contain the integer property with the H and then and the Handler we would do checks whether that user is over the minimum required age so that's basically what we're doing in here we're targeting the claim that holds the permission and when there is one a valid one we'll check we're just checking if we're authorized which means the difference there's overlap between the user permissions and the required permissions and then we're authorized in all other cases if there's no valid permissions then we just do nothing we just exit so this Handler just evaluates whether the user has sufficient permissions and in here you also see that we're trying to get the integer value from the claims and we're casting those back to the permissions enumeration to then work with those to the checks let's take a look at the next one the flexible authorization policy provider which is basically making those policies on the Fly at its first checking do we already have a policy with the name for example permissions 5 if not we're making one and we're registering that policy to our app and this policy name helper is basically just translating permissions to policy names and vice versa to actually get this custom permission claim in our identity we'll have to add this custom user claims principle Factory and we actually only have to do that in the back end since the back end is going to generate the bearer token so that's basically what that claims Factory does it's getting all the roles of the user and summing up all of the permissions to get the total of permissions for that user and then adding that as a claim to the yeah better token to the user claims principle so that was all for the back-end setup so now we can protect our API endpoints with so I added some endpoints so the identity and points which you saw before and then I added the roles and the users and points which I have not protected yet but you could simply say require authorization and then you pass in the stringified version the policy name the rows whatever you could even and that's where this policy helper name helper comes in generate policy name four and then we could pass some permissions dot let's say few users are manage users for example and that's then going to result in the policy name of permissions Buddhism and teachers some of 4 and 8 so 12. I think we can just use the authorized attribute and then specify the permissions the same way so it wasn't again a few users well we're in the roles so roles would make more sense and manage roles I'm not sure if I'm doing it correctly yeah and that's where Mr Taylor has made an another authorized attribute it's not using the default one since the default one cannot does not support passing permissions there so let's take a look at the attribute Mr Taylor Made for us living in the shared project authorized attribute should basically inheriting from the standard attribute has some Constructors you can also pass the policy name but you can also pass the permissions and this will basically translate the permissions to a policy name so we can use this attribute in both on the back end as in front end to protect our endpoints or our Pages for with that with those permissions so what else do we have in here we saw the attributes we saw the flexible policy provider we saw the authorization Handler and the requirement and even the policy name helper we've seen as well and the permissions itself which holds the permissions and an extra method which is only used in the front end to display those permission names yeah I made an admin State and admin HTTP client simply to separate out the users the role stuff so what we saw before with the authorized view of Blazer out of the box that could only have a policy name or Mr Taylor who made a flexible authorized View but similar like the authorized attribute which inherits from the standard authorized View well translates the permissions into a policy and to Simply check whether there is an overlap and permission you can also use the hash flag and underneath we see so we're initializing the rules just to have the the table of check boxes with the roles and the permissions and then whenever I click on such a check box we're calling this update role permission so to update the permission of that specific role doing that HTTP client but first we need to either Grant or revoke those permissions so add permissions or take permissions away so that would go as follows but those operators that we saw before what was it the aura and the ixor let's take a look at the admin page and you can of course specify multiple so if the user has any of these permissions dot manage users but that's where the fine graining comes in so you could for example say on the page you can use that attribute as a authorize so you need to have the view yeah maybe admin or few users permission to access the page and then down below to actually interact with the stable maybe we only want the ones that also have the manage users permission done for the roles table the rules permission then you have the delete roll button which should actually also be wrapped in one of these flexible authorized views and then we have the fine graining of managing roles so adding rules that needs to specifically needs to manage rules permission so that's all very useful the fine graining I would say it's more useful in an admin panel than in an uh yeah just front-end project that I'm working in right now but it's very flexible look permissions 31 let's see what that is so few the users manage the rules and you have View and manage the rules so we can also add rows but we cannot manage the permissions we can only view the permissions see can't click because only the administrator has the manage permissions so we are now ready for organizational changes a change in and stuff let's say some new people come in some new developers or some new managers or some new this or that functions they can just yeah get roles get permissions and we don't have to change anything and the code however if we add features so maybe the products we might have to go into the code base to add those permissions few products manage products and so on so that's still hard-coded there might be a way to also store these permissions into the database but then you'll have to likely load them at Star app startup I'll have to investigate what the implications are from that what the possibilities are there I might want different permission sets per module even or maybe different permission sets per application let's say for the administrator application you want a different set of permissions then for the webshop for example so does every project need this no of course not if you just want to protect a few endpoints or a few views with one or two roles then role-based or policy based might be more than sufficient for most of the applications if you do have a lot of changes and access levels or roles or these kind of things and you don't want to you don't want to have to go into the code base redeploy each time then this might be a very good solution for your project so I'm going to at least try to make some kind of member section with this and it makes a lot of sense for me to have permissions per module per feature rather than having those rules all over the code base I'll end the video right here I will publish this code to my patreon and I'll publish my other adapted more module approach as well which will only deviate a little bit in the front end and I'll say it again I highly recommend you to watch Jason Taylor's talks about the subject and his blog post even on his GitHub repository I forgot to show one thing in our project in the pre-render server I have to add this add authentication and add pair token and that's also part of the reason why I'll stick with my adapted modular approach because I want to minimize the amount of places that I have to add or modify code to make this authentication module work since this needs to be relatively easily plug and playable if you like this video don't forget to let me know by hitting that like button and make sure to subscribe because there are some more videos to come for this series and I'll make sure to publish the code into patreon this version will also contain some big fixes that I accidentally introduced in my last version which is the ones you see on screen so and this version contains the ability to manage roles and permissions and much more
Info
Channel: Keep it simple, stupid.
Views: 6,337
Rating: undefined out of 5
Keywords: web, app, development, dotnet, pwa, ml, ai, frontend, backend, cloud, azure, fullstack, .NET, C#, machine learning, artificial intelligence
Id: rCnsJwMc6-I
Channel Id: undefined
Length: 32min 32sec (1952 seconds)
Published: Sat Sep 30 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.