How to Manage User Access in NestJS | Authorization with CASL

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey today we're going to cover castle and how to integrate it with nesgas so i have a couple recommendations for you if you haven't seen them before first of all i would recommend that you watch uh the last video i made actually was on castle and the fundamentals of how to use it what it is and stuff like that and then i also had this video on sgs authorization which covers the basics of how guards work and then finally you know you can't really do authorization in an application if you don't already know who the user is so ideally you have authentication in place so if you don't know how to do authentication for your application i also have a video on that i talk about how to do you know username logins and jwt sessions stuff like that all that good stuff it's in that video alright so let's jump right into it so i have a folder here in my desktop it's called nest castle and what i'm going to do is i'm just going to initiate a new nest project in here ideally you also already have the nested scli installed globally here's the command if you need to copy it i've already got that installed so i'm just gonna do nest new and then and i will scaffold a new application for me i'm gonna select npm and that's going to install my dependencies all right so that's already installed and you can see it generated a bunch of files for me on the left here now right off the bat i'm actually going to add another dependency which is castle itself so make sure you install at castle ability now before we get started it's probably a good idea to design some sort of api that we're trying to protect with authorization so imagine that we have user crud right so we might have get user get user buy id you can post a user to create a user you can patch or maybe a put would work there as well and you can also delete right but in a typical application you don't necessarily want to provide all of these capabilities to every single user so let's imagine that we have the concept of an admin so let's say that if you are an admin so let's have a variable called is admin you can basically do everything right you can create read update delete so all of these and if you're not an admin we're just going to say that all the only access that you have is to read right you can read the data you can see other users you can see your own information but you can't update or delete any user and we're going to evolve these requirements as we go so we're going to revisit this later but this is sort of our initial requirements so to get started if you didn't know nest actually has a really nice cli that that allows you to generate a new resource and it'll give you all of those crud endpoints so we're going to do nest ge which is generate for short resource and we're going to do user and i'm going to select rest api here although by the way the self recovering here it doesn't have to be rushed it could be it also applies to graphql which since the concept of guards it doesn't care what your transport layer is it still works regardless of you know whether you're using rest or or graphql but for this demo we're just gonna stick with the simple rest api and we're gonna hit yes here to generate crud entry points so you can see that it created all these files there is now a user controller you can see that this actually generated all of those routes that we wanted in our requirements right so we have our get user we got one for get user id and then we have a patch a delete and a post for create right so this is basically all the the requirements that we have so far so our goal is to restrict this api to provide this specific access again this is our requirements we're going to keep revisiting this now one of the things that got generated also is this user entity which is going to define effectively what our user object looks like and this could also represent a database table if you wish like if you were using typeorm you can do that so we said that a user well first of all they have probably some kind of id and we also said that there's some kind of boolean property that determines are they an admin or not so we're going to add is admin right so we're going to start with that it's going to be very simple so next what we're going to do is we're going to create a module for the authorization stuff so all the castle stuff right next gs is very big on encapsulation so we're going to create a module we're going to do an sg module and let's call this ability and while we're here we're also going to create a class ability since this is actually the folder of the module we just created so src slash ability we're going to do ability slash ability dot factory right and you can see that that created us a file called ability.factory we're gonna open that up and this is gonna be the main file where we define uh the user rules and permissions so the first thing i'm gonna do here is i'm gonna add injectable here to make sure that this is you know it's a provider and then i'm going to add a method called define ability for and that's going to take in a user right so that's going to have the type of our user entity and this is where we're going to define the rules the different abilities that the user has now with castle like i talked about in my last video you can define a set of actions in a set of subjects and basically your rules your permissions is just a combination of all the actions that you can do on a certain set of subjects so first let's start by defining a set of actions for our application generally most people can start with just crud you know create update delete and then manage since manage is sort of a special action in castle it's sort of like a wild card for any action all right next we want to define the type for subjects and what are subjects it's really anything that you may or may not want to restrict access to and typically that's just your your entities right because you typically would want to protect who can update or create any of those entities who can delete them just like what we're trying to do with users so user is one of our subjects in this simple example now subjects in castle could be as simple as a string but they can also be classes that can be objects and since castle is written in typescript we actually want to make sure that we're using the correct interfaces when we create these types so for example if we want to say that user is one of the subjects we can use this in first subjects from castle you can see this is importing from castle ability and we're providing the type of user right so that's generally how you provide your your subjects and if you have more than one subjects like in our case right now we're starting with just one you can add it to here so for example you can do type of you know maybe you have a post subject entity right so we're going to go back to just user and then you'll notice that we're also doing all because all is a wild card for any subject right just like how we have a wild card for actions which is the string manage all is the wild card for any subject and then effectively we want to join these action and subjects together to define the overall type for our castle ability so we're going to add type app ability i'm going to import this ability from castle ability and you can see that it's saying we're creating an ability that specifically has these actions and these subjects so with that in place we can now bring in our ability builder so if we did builder equals new ability builder from castle and to use ability builder you actually need to provide this ability object in here right so that's generally how you create a ability builder with castle is you use the ability builder passing this ability object in here and then you can start using that builder right and this builder provides methods like dot can and that's that's the main thing that allows us to start defining what can a user do or can't do right and you can see that can takes in an action or a subject now there's one catcher because we're missing something uh you'll notice that we haven't taken advantage of what this app ability is yet so you'll notice that if i provide a random string in here like test it this assumes that we have an action called test because it doesn't know about the this enum that we created right so to improve uh the types here we need to make sure to cast this ability object to our app ability and the way we do that is we're going to do as ability class which you also import from castle ability and then providing their the the custom type that we just created and now you can see that we have red squigglies here because it's expecting uh this enum that's expecting a for example action dot read right and it's also gonna do the check for us to make sure that this is a correct subject so for example if i just provide a random object in here it's gonna break but user should be allowed right so at this point we can actually start defining the permissions for the different users that we might have now to make things a little bit simpler i'm actually gonna deconstruct can and cannot and build so that we can just do you know can right so let's go ahead and open up our requirements again and our goal is to now start implementing our our requirements on the right here so we said that you know our user can be an admin so if we did if user is admin we can give them certain permissions so we can do can action create user and you can repeat this for all of the actions like create read update delete or we said that manage is a wild card for all possible actions since our requirements say that basically an admin can do anything we're just going to change this to manage right so this says that an admin can basically do anything with a user entity and you can even change this to all if you wanted to which would allow an admin to basically be able to manage anything across the entire app it's really up to you how much you want to restrict this let's just start with that and we're going to say that if you're not an admin the only thing that you can really do is action dot read and again you can also specifically provide the user type here this the user subject but you know typically for a non-admin user they would have read access to most things in your application anyways right and again this is assuming that you have authentication in place so assume that they are the user is already logged in you know let's just say that they have read access to everything right so those are very simple requirements that pretty much allows us to do what we have defined here so far and you'll notice that we haven't used cannot yet we'll see an example of that in a little bit uh you know we're going to evolve this as we go but for now what we're going to do is we're just going to return build and this is going to build our set of abilities for a given user right that's why we have definability user now there's one piece of configuration that we need to add in here which is detect subject type and we're going to make sure to import extract subject type from castle ability so this is just saying that if it sees an object it's going to look at that object's constructor and it's going to figure out if you know what subject it is that we're trying to talk about right so for example if we did change this back to can user read right it's going to check that it's actually of type user so i hope that makes sense but if it doesn't there is a documentation on subject type detection in castle if you want to like learn the deeper details about it all right so now that we have defined our base permissions and we're going to update this more as we build this out make sure that you know because this is a provider we're going to make sure that this is actually in we have to make sure that this is actually in our ability module providers right so we have to add that in here and you also want to make sure that it's in your exports array that way other modules can import your your factory so as an example if we had the user's module you know we can add in here a imports ability module and since we had the ability factory as an export of ability module that means that everything else inside this user's module can now inject that ability factory let's go to our user controller and that means we can now do something like this private ability factory which is a type of our ability factory right and at this point let's actually just run our application so that we know what the current behavior is before we started protecting some of these routes right so in my terminal i'm gonna do npm run start dev and that's gonna start my application in localhost 3000 and then i'm going to use thunder client here which is it's kind of like postman if you haven't seen it before so if i do a get on 3000 slash user we get back on the bottom here this action returns all user and actually i made a mistake earlier i should have named this users not singular user so i'll just rename the path here to be user so that makes a little bit more sense to me right we're getting slash users a set of users all right so we have that in place so and you can see that we again we have the different methods right so for example we can also do post on slash users and that's going to return as a 201 created and a response that says this action creates a user we can also do delete on user slash id right and we see the response says this actually removes the user same thing for if you do a patch right now we need to start protecting these routes so that only admins have access to managed users so how do we do that right so remember that we now have this ability factory injected into our users controller so let's start with the create here we're saying that only admins can create a user so we're gonna do ability equals this dot ability factory that defined ability and then we said that we need to provide a user object here and what is that object that's gonna be the current user now typically again i mentioned that you ideally already have authentication in your application and the general convention when you do authentication you know with nest or express right is that usually you'd have the user in you know request that user right but we don't have that right now because we didn't implement authentication in this application so we're just going to imagine that this exists okay so imagine that we do have request that user and that brings back an object with an id of one and we're going to say is admin is false right so imagine again that we have auth the user logged in this is their details and typically that's being pulled from request.user but because we don't have it we're going to mock it so we're going to take this user the current user i'm going to provide it to our factory and that's going to create us an ability and remember that ability effectively defines you know what can and can you not do all right so with castle there's pretty much one way to check if a user has a certain permission and it's sort of like this so let's say that we have a variable is allowed and to determine if the user is allowed we're going to do ability dot can right so this is very similar to the same method that we used to define it's also canon is also what we use to to do the actual check so we're going to say action dot and we're going to need to import that enum that we have from the factory so we're going to do action.create a user and we'll also import user from our entity class file right and very simply if is not allowed we're gonna throw a new forbidden exception and if you didn't know this is one of the built-in exceptions in so yes if you throw this specific class it's automatically going to respond with a 403 i believe so for example let's provide a message in here like only admin right and now let's see how our application behaves if we try to do a post on slash users and again remember that our fake current user is not an admin so if i hit send here it's gonna send me a status of 403 forbidden response with my message in there right so that's really the basic gist of it is that you you need the the current user you know ideally from your authentication solution and then you create the ability using that user and your factory here and then you do a check now there are also other ways to do this in more advanced ways to do this with guards which we'll we'll cover in a sec but before we get to guards i also want to show how to use the forbidden error class from castle so another thing that you can do for example is let's do a try catch block here what you can do with castle is use this forbidden error class you can see it's from castle ability so we're going to import that and this exposes a method called from which you provide the ability to which we got from our factory and then it has a another method that you can chain in here called throw unless can which is effectively the same exact can call that we have here except that it's automatically gonna throw a specific exception if it can't right so we'll also take our action and subject user in here provide it there and then we're gonna move this return the actual service call to create the user within here and then if you want to you can specifically catch this specific error and then you know turn it into a different type of exception kind of like the forbidden exception that we have here so we can do if error is instance of that forbidden error we're gonna do forbid an exception error that message right but we where do we define the message there's a couple places that you can do this in so one is you can actually add a set message method here and make sure this is before the throw unless can and you can you know your add your message in here right and let's see how that behaves it should behave differently but we'll get a different message so if i do a post 3000 slash users send same thing 403 forbidden but we have a different message right so this is effectively the same thing as this one which i can imagine someone is probably thinking but isn't the one at the top simpler uh to a degree it is but you probably don't want to keep doing this if statement and throw everywhere because you know this is throwing a specific error there is a very specific uh benefit to that that error that's being thrown because in in sjs there's this concept of exception filters and you can define basically a global uh catcher of sort right so like the the exception filters is actually there's one that's built in that's capturing that's catching these forbidden exceptions however if you wanted to catch a specific exception or a specific error you can define a custom exception filter so for example kind of like how they're doing here you notice that they have an exception filter that catches everything but then they check what instance of that error that exception is being thrown and in here you can instead check is it an instance of forbidden error and then you pretty much can remove this right catch block and just globally do that catch everywhere right so this actually ends up being cleaner for you if you start using exception filters so this code effectively just becomes like this and then if this does throw it's automatically gonna be caught by that custom exception filter and that becomes very clean in my opinion so that's the reason why i specifically introduced that here but since we didn't implement the exception filter we'll bring back the try catch here and there's also another benefit of using forbidden error is that you can actually set the message on the the definitions themselves in your ability factory so for example if you you can also define the inverse using cannot right so if i explicitly provide a cannot rule like action dot create user the inverse rule actually has this extra method called because and i covered this in my castle video but this is a summary this basically allows you to define your special message in here which basically allows you to centralize all of your forbidden messages in the same factory that you have here right so it sort of centralizes everything in one place and now i can remove the set message in here and let's do another simulate post on slash users and now we got our new message here that's coming from our factory right so as you sort of implement these pieces it starts to get more and more uh cleaner right so that's the primary benefit of using the forbidden error throw unless can is it can utilize those messages if you want to provide that context to your your api consumers now if you don't care about that and you're okay with like a generic you know four or three forbidden you can't access this you don't really want to provide messages then you can just stick with the simple uh cans and don't provide the inverse or messages and you know that's also another way to do it it'll be a little bit simpler all right so let's take this a little bit further in our requirements let's add another requirement that says you know let's say that you know our user object now has the concept of organizations right imagine that you know you have groups of different types of users and you have the admins can only manage the user in their own organization right so let's add to our requirements here of if admin they can do all of these if in same organization so what we're going to do is in our ability factory we're going to go back in here and we're going to add an explicit rule that says you cannot action.manage a user if their org id and we're going to add this in our entity in a second here we're going to say if their orga d is not equal your own org id because you can only manage users in your own organization right and this is actually a if you haven't seen this before with castle i recommend reading the documentation for conditions in depth but basically what they did is they tried to simulate a similar query language to mongodb right so they have these different operators like equal not equal less than less than or equal to greater than etc right so there's a bunch of things that you can do to add conditions to check if a certain object has the right properties that you expect it to have right so that's why you're here we're saying the org id of the user that you're trying to manage needs to have the same orgardi as you now there's write squiggly here because we don't have org id in our user entity so we're going to add org id number and back in our factory that should be looking pretty good and we'll also need to clean up our our mock users here so we're going to add uh org id one here just so we don't have the errors but anyways now that we have that new rule in for for updating we can do the same exact thing that we're doing here in update but there's a there's a tricky part to this which is that uh you don't already know what org the user being managed this until you pull it out of your database right and typically you would define that logic within this service method that we have this is probably going to query uh the user from the database and then update it right so if i copy that code down to here in our update we can do the same and let me also copy this try catch down here but we're going to replace the return to be you know our update but there's something missing here right if we just update this to be uh action.update user how does it know what id is the user that we're updating right and it basically it doesn't it needs to be pulled out of the database first if you did have a database so you have a couple options there one is that you can first do something like you know user to update equals this.userservice.find1 this is one of the uh sort of mock functions that they auto generated for us you'll see you know this returns an action with an id right so if we were to provide uh the id in here and that needs to be a number and then we can take that user to update and provide it here as a subject instead of just a type right but we have a squiggly here because this is returning a string and not an actual user object like it should so if we go in our find one let's do we can kind of mock the behavior here by creating a new user you know but imagine that we're actually pulling this from the database so let's say that this user has an id of two and let's also say that their arg is also two and actually we'll just do the id to read the same here because we're trying to mock that being pulled from the database right so we're just going to return that user and now i think that the types should work out so that this is actually a user object and now we can use it here and this should work right so if we let's try to test here if you were an admin but you're in org id1 remember our user to update is in org id2 right so this admin should not be able to update this this user so if we do a test on patch slash user slash 2 we're going to get a forbidden saying you can only manage users in your own organization and if we were to change our org id to 2 here just to make sure that it works let's do a send and we'll get a 200. let me put this back to one here so that's working so that's one way to do the forbidden check if your if your subject is an actual instance of an entity you actually need to pull that entity from somewhere or create it and then provide it here as a subject now if you don't want all this logic to be happening in your controller however what you can instead do is just you know in your user service update here you can pass in the current user and then you can do this querying inside uh the update so for example let's uh refactor this to be inside our update method here which now also takes in the current user and we're going to say that user to update is uh this dot find one and then we just got to make sure that we have all of our dependencies in place so we also want to add so we also want to have the same factory injection that we have in our controller here and put it into our service and then so at that point we can also move our ability factory call to be in the service method let's put that up here and do current user definability for current user and i made a typo here this is supposed to be in the constructor not in the create method so let's do constructor paste that in there from our ability factory right and also import whatever else is missing forbidden error and the action right so then it's going to do that forbidden check and then if it's not forbidden you know this is where you actually do update call db right update it in your actual database and then return whatever the value of that is right now we're gonna keep it in just returning a dummy string right so going back to our controller starts to get a little bit cleaner of just having the update call in there and then the update is gonna have all that business logic of checking whether or not that user can access the user that's being updated right so i think if we call our patch here again it's going to get us our 403 so that's working the same as before right so that's just an alternative way and i'm not proposing a specific how you should do this it's really up to you but generally in in sgs you want to move all of your business logic inside the services and then anything relating to routes and you know http exceptions and stuff like that that's the stuff that you want to have on the controller right so you know you could do the same cleanup for the create as well but i'm going to leave that as an exercise for you all right now let's get into the more advanced stuff so it's probably pretty painful as you can imagine having to constantly you know pull in the user and define the ability and do a forbidden check forbidden error and do what can user do action subject right it'd be kind of painful to redefine that everywhere uh so that's where we can start defining a a specific guard that's going to do the check for us automatically so let's start working on that so you might know from my previous video on an scs authorization is that you can define basically custom decorators if you want to so the way to do that is first we're going to create a we're going to create a abilities decorator dot yes and what we're going to do in here is we're going to define a new checkabilities decorator which is going to require a set of requirements and that's going to provide us some metadata we're going to do set metadata from sgs common and we need to provide a key in here which i'm actually just going to define in a variable so we'll do checkability and then we just pass in the requirements from the arguments and this actually should be expert const and it would also be nice to actually define the shape of this requirement so we're going to do basically an interface of just action and subject so make sure to import action and subjects from the factory so we'll say that requirements is a type of required rule that's you know an array because we have you can have one to many so what that's going to allow us to do is we can start providing metadata to a specific route so i can do something like uh let's go to a different one let's go to our delete you know i can do something like at checkabilities and let's import that from new from our new decorator and we can provide the metadata in here so i'm going to say that for this route to define action that it is an action dot delete on the subject user right so that provides metadata which we can then use in our guards to do the actual check right so this doesn't protect the route but it provides just information so how do we take advantage of that information ideally we have some kind of guard here right that does something like you know imagine we had a used guard abilities guard let's go ahead and define this abilities guard that is able to take this metadata and determine if a user can or cannot proceed so back in our ability folder i'm going to create another file in here called abilities.guard.ts now to save you some time so you don't have to watch me typing this out i'm just going to add the code and then i'm going to talk about it so our guard is going to look something like this and again if you watched my original sjs authorization video it talks into the details of how to create custom guards and this is one of them right a custom guide is basically a class that implements can activate and can activate has to return a boolean and if the boolean is true it says yep you can proceed with this route and if it's false the default behavior is that it's gonna prevent the the request to go through and it's and it's gonna return a response of 403 now in our code what we're doing is we're using the reflector to pull back the rules that we're providing so as an example right in our check abilities here in the delete route we're providing this object so we're just extracting that metadata into our guard into a set of rules here and then within this method we're also getting the current user again i have to reiterate that uh if you had an authentication solution typically that user object you know if you're using sessions or something like that is gonna be inside request.user and the way you typically would get that is by getting it out of the context and then getting the request from that context and the user will be in there but because we don't have auth in this demo to keep it short we're just simulating it with this current user object that actually i didn't define we'll do that in a second but imagine that is our our current user as if we had authentication and then the rest of the logic in here is the stuff you've seen before so we're gonna define the ability from my factory and we're gonna go through every single rule right because you have you can have one-to-many rules and we're gonna say if any of those rules is you know it's it shows that you're not allowed we're gonna throw the forbidden error and if that forbidden error is thrown we're gonna catch it and we're gonna throw a specific forbidden exception error and this is just so we can utilize that message you know if you just return false that works true but you can't use uh that's the special message that you have so i'll show an example that in a bit otherwise if you go through all the rules and it shows that yep you have all of the access then we're just gonna return through and it's gonna proceed right so let's see this in action first of all we need to define our current user which we said is in this file uh user slash current user so we'll just make a new file in here call currentuser.ts and we'll just again define a dummy user in here of type user right so id1 is not an admin and is an org id of one all right and then back in our controller here we're gonna make sure that we import used guards and ability guard and now this protects our route with just a set of decorators saying you have to have the access to delete a user so remember that right now we said that our current user is not an admin so they shouldn't have access to delete anybody so let's do a quick test back in our thunder client we're gonna do we're gonna do a simulation of delete on user slash one uh and then hit send and it's gonna say cannot delete on user and remember you can provide custom error messages here if you do that in your factory so for example you know we can provide an explicit cannot shin.delete user because you just can't right so if we hit send here you get back your your message you just can't and this is where the explicit catch here is is very useful like i said if you know you could just return false if you want to so if we didn't use this for example we can instead do return rules dot every rule and you can just check against the ability directory directly you can do ability.can rule.actionroll.subject and that's the same thing right because in a guard you just have to return a boolean that's all you really have to do but the disadvantage there is if you hit send here you'll get a 403 but you can't get that message that you defined so it is a little bit simpler but if you are defining messages like you have we have here which you don't have to you can just do a an every here instead of uh throw catch try catch let me just bring this back to this right so let's talk about a couple other tips that i would provide so um even this this is a little bit more uh cleaner than having to do you know this explicit you know ability building yourself right but uh it might also be nice to create like pre-defined rules that you can provide here so perhaps create a specific required role that you kind of just pass around like so for example if i'm going to put it in this file but you can really put these things anywhere you want so for example if i define a specific read user ability which is implementing this interface right or you could also do an object if you want if you don't want to deal with classes if we just define the properties of that to be the action and the subject that we want now we have a reusable metadata that we can just pass around so for example in our you know our finds right so because this is both for reading users instead of us having to do this paste this in here both times and both of these would have to be read right so if you wanted to clean this up a little bit so you don't have to keep repeating this object you can just use our new bead user ability right and you can just provide it in here instead like new feed user ability and we'll copy that down here and let's do a quick check of just reading you can do get on slash users and as well as get on slash user id and just so you know that that actually is working let's flip the can read user here for non-admins to cannot and let's do another test on get slash users and we'll get our 403 forbidden right let me bring this back just so you know it's working so that's another pattern to to do it now the other thing we can clean up here is you know it's kind of painful to keep doing used guards ability guards you should know that you can actually define guards globally if you want to so maybe let's go to our uh main module or app module and what we can do here is we can provide a global guard provide app guard and we need to import this from sgs core and we're going to do use class ability abilities guard right so importing that from our abilities guard file and now this says that this enables our guard to be global across our entire application so that means we can get rid of all these and we should be able to let's try a delete here on since we have a non-admin so i expect this to 403 right so that still works as as it did before right and then of course you know remember that your your how you define your permissions here in our factory is really as it can be as simple or as complex as you want it to be so for example uh the example we had with update earlier where it takes in a condition right you can't really you can't really do the condition at the guard level unless you you somehow pull in the data in the guard which you can do but that's kind of a mess so i would recommend as much as possible do it at the guard level and if you can't do it inside the service and then there is one other thing i didn't really cover it in this video but i did in my castle fundamentals video another thing you can do with castle is in addition to conditions you can actually define specific fields that they can manage so like for example one of the things that you can actually add in here is an array of fields as you can see here so if you want to restrict it even further than just the entity but you want to say within this entity what fields you have access to so for example maybe you only want to allow a user to be able to read the name of the the other users but you know maybe your user entity has passwords in it so you don't want to expose that so that's how you can also add fields to your specific definitions here but we didn't cover that but you can you know extend your your check abilities here to also take in fields so you want to do right so you can provide an array in here as well for your can checks so that's just i'll leave that as an exercise for you but i'm just calling it out that we just defined a simple case here if you have more complex uh scenarios you're going to want to update your your guard right so like if you were to pass in fields in here you can pass that ultimately into your rules and can activate in the guard and then run that through right so i think this is probably a good place to stop uh so you i've shown you a couple different patterns here i don't really have a strict recommendation so it's really up to you to take which of the patterns that i showed you is best for your use case you know whether you like using the guards or whether you like using the check inside the services or a mixture of both as i sort of recommended here and it's also up to you you know what the signature of these decorators are if you want to make it more custom for example in the an sjs documentation actually where they show the castle integration there's their implementation or suggestion is a little bit different where instead of you passing in an object like this they actually show an example where you pass in a function like a callback that provides ability so that your signature looks like this ability right so that's another way to do it you can provide your actions in here you would just need to change the signature a little bit and that is exactly how it's documented in in the next gs documentation but i i find the the one i showed in this video a little bit simpler but i wanted to show that you can you also use this pattern the only difference is it exposes the the canned ability object to the controller whereas mine hides it so it's up to you what your your ideal is right so again it's it's fairly customizable it really is up to you how you want your api to look all right guys that about wraps up this video hopefully you got some good ideas out of that i definitely personally recommend castle myself i think it's a great authorization library and i've tried a couple other ones before in the past as well and this is probably at the moment my favorite again if you want to learn more about castle authentication authorization i do have those other videos i'll leave links in the description if you want those anyways guys i gotta run so make sure you subscribe if you want to see more of these and i'll see you on the next one
Info
Channel: Marius Espejo
Views: 33,482
Rating: undefined out of 5
Keywords: nodejs, expressjs, express, node, casl, accesscontrol, acl, rbac, roles based access control, abac, attribute based access control, authorization, authentication, nodejs passport, nodejs jwt, jwt, node auth, node passportjs, nodejs authorization, nest casl, express casl, nodejs tutorial, javascript, typescript, prisma, casl prisma, nest auth, nestjs auth, nestjs passport, nest authorization, casl typescript
Id: 1pPjCX0FHco
Channel Id: undefined
Length: 46min 20sec (2780 seconds)
Published: Sun Feb 13 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.