Ready to get started?

Join Adocasts Plus for $8.00/mo, or sign into your account to get access to all of our lessons.

robot mascot smiling

Applying Our Server-Side Authorization Checks

In this lesson, we'll use our access controls to add authorization checks to our controllers where needed. This will help ensure members can't update, delete, or invite users.

Published
Jan 31
Duration
13m 0s

Developer, dog lover, and burrito eater. Currently teaching AdonisJS, a fully featured NodeJS framework, and running Adocasts where I post new lessons weekly. Professionally, I work with JavaScript, .Net C#, and SQL Server.

Adocasts

Burlington, KY

Get the Code

Download or explore the source code for this lesson on GitHub

Repository

Ready to get started?

Join Adocasts Plus for $8.00/mo, or sign into your account to get access to all of our lessons.

Join The Discussion! (8 Comments)

Please sign in or sign up for free to join in on the dicussion.

  1. Commented 1 month ago

    Hi Tom, I'm currently building a task management application, and I find it pretty similiar to your project in termes of "architecture". I have a workspace model that could be assimilated to your organization model. So when it comes to setting the active workspace feature I did the same thing as you did, same for ACL, abilities etc. So basically if the authenticated user is not a member of a workspace, it doesn't appear in his list of workspaces and then cannot set it as active.

    But I'm facing a problem when I tried to get access to a workspace page, that the authenticated user is not a member of by putting the workspace id in the URL. Since my user has another active workspace in which his role is ADMIN, then, the user can access the workspace even if he's not a member of it.

    I was asking myself if you managed it, if I missed something, or if it's "normal" and I need to modify how I check the user's role and stop using the active workspace ?

    Sorry, I think this is not very clear, pretty hard to explain it since I'm a bit lost in all of those concepts 😅

    1

    Please sign in or sign up for free to reply

    1. Commented 1 month ago

      Hi emilien! I think I'm following correctly, but let me know if this sounds off base.

      So, we manage this with our organizations by querying the active org through the authenticated user, which ensures the user is a member of the org. If the user sets an id of an org that they aren't a member of, our query won't find a match and will instead overwrite the user's active org to the first org found that they're a member of.

      For our application, the active organization is determined via a cookie. It sounds like you might have this set up as a route parameter.

      If that's the case, ensure you attempt to query the workspace through the authenticated user. If a workspace is not found, you'll want to either:

      1. Throw an unauthorized exception to prevent the user from working with the workspace. You can then offer some button to take them back to safety.

      2. Or, find a valid workspace for the user and redirect them to it. You'll also want to notify them that they did not have access to the previously requested workspace.

      The first option there probably being the best as it will ensure the user knows what happened. You don't want to continue onward as the URL contains an invalid id for the user, which could accidentally be used to load something or on subsequent requests sent from whatever page is rendered as a result.

      Hopefully that's at least a little on point and helps a little. If not, please feel free to share your query/flow, or a representation of it, and I can try and see if anything stands out.

      1

      Please sign in or sign up for free to reply

      1. Commented 1 month ago

        Hi Tom, thanks for your reply. After reading my first comment, I think I was not clear at all 😅

        I also use a cookie for the active workspace.

        I'll try to explain my problem a little bit better :

        • user A is member and admin of workspace A → id = 1

        • user B is member and admin of workspace B → id = 2

        Everything is fine for the moment, according to my ACL if the user A goes to '/workspaces/1' he can see the page. Same for user B if '/workspaces/2'. This URL will trigger the show() method in WorkspacesController. You won't see the use of the ACL in this method in the repo cause I did not commited, but I used it like you do in your tutorial.

        My problem is that if for some reasons, the user B goes to '/workspaces/1', he can still view the workspace, however he's not a member of it. I reproduced the same logic as you did to get the active workspace

        I probably have missed something or there is a point that I do not understand. Maybe you already pointed it out in your answer, and if that's the case, I'm sorry. But I'm a bit confused, it's the first time that I have to work with permissions.

        1

        Please sign in or sign up for free to reply

        1. Commented 1 month ago

          Alrighty, I think I see what's going on! Where your project differs is that your /workspaces/:id route merely renders a page. In our project, and even in your main branch, this instead sets the active org/workspace in our PlotMyCourse & on your main branch, then redirects back to the dashboard.

          Where I think the confusion comes in is the /:id in your /workspaces/:id route is merely symbolic since you're actually loading the workspace via the user's cookie. So, the displayed workspace is whatever is stored in the cookie and not what is provided via the route parameter id. Things do seem to still be working, the issue is that the id in the url can differ from what is actually displayed. Which, can lead to issues if you were to ever actually use the url's id for something.

          So, to prevent that possibility, I would either

          1. Stick to the cookie and get rid of the /:id in your /workspaces/:id route to instead have something like: /workspace or /workspaces/show

          2. Or, drop the cookie and instead use the id route parameter.

          To add, there isn't an issue with using /workspaces/:id/active to set the active workspace. The issue is that the new /workspaces/:id route that shows the workspace has two spots it could pull the id from; the id route parameter in the url and the cookie, and those can differ from one another.

          Here's a video walkthrough of the behavior I was seeing on your feat/workspace-roles branch. This shows how user-a could request workspace b via /workspaces/2 but actually still saw workspace a; meaning the id in the url did not match the workspace used.

          Here's another walkthrough of the behavior I saw on your main branch. In this branch everything works fine.

          Hope this helps!!

          1

          Please sign in or sign up for free to reply

          1. Commented 1 month ago

            Of course this helps, could have spent a lot of time on this. That is so obvious with your explanation… Thanks a lot. Oh I feel so dumb, I created a route with a parameter that I don't use…

            I think I also need to take time to document the flow of setting an active workspace etc and understand it much better. Completely forgot that the middleware kind of "block" access to workspaces that the user is not a member of.

            Thanks again Tom ! Loving your tutorials and your fast answers to comments ! 😊

            1

            Please sign in or sign up for free to reply

            1. Commented 1 month ago

              Awesome, glad to hear that helped clear things up! Ah, please don't feel dumb about that, it is just a small oversight. We've all done a lot worse!! 😊

              That sounds like a great plan! Having a document/diagram of how things work would definitely help. That's something I'd like to make a more concerted effort to do in-lesson.

              Anytime emilien!! Always happy to help where I can! 😊

              1

              Please sign in or sign up for free to reply

              1. Commented 27 days ago

                I've tried to make a flowchart of the middleware and how it uses both, GetActive and SetActive actions. It is related to my use case (workspace and not organization) though, but I think the logic stays the same.

                I don't know if you'll find it useful, but just in case, here it is. Let me know if there are any errors or inconsistencies. It was really interesting to do and taught me a lot, maybe I could help with this kind of thing if needed, don't hesitate, it would be a pleasure.

                1

                Please sign in or sign up for free to reply

                1. Commented 26 days ago

                  Oh nice! Yeah, this looks spot on, nicely done emilien! Thank you, I really appreciate that offer! I'm happy to hear that going through this was fruitful!! 😃

                  1

                  Please sign in or sign up for free to reply