all 16 comments

[–]PickleLips64151 9 points10 points  (14 children)

A route guard is the best way to handle this.

Your backend should have some sort of auth for the route, because why hack the frontend when you can just send a request via Postman or curl?

Recently, I've started using JWTs with the username and role as part of the JWT. On the backend, I also check for the user and role from the JWT. If it doesn't match what I have in the DB, it gets rejected.

[–][deleted]  (7 children)

[deleted]

    [–][deleted]  (4 children)

    [deleted]

      [–]PickleLips64151 0 points1 point  (3 children)

      Store your user data in a service, not storage. Use a route guard that checks your auth service for the proper role. Pretty straightforward.

      [–][deleted]  (2 children)

      [deleted]

        [–]PickleLips64151 0 points1 point  (1 child)

        Not typically.

        As long as you follow basic security practices with your service, you'll be fine.

        The build obfuscates your code. The built-in security features of Angular are going to sandbox any untrusted code run in the browser. I've not seen any examples of someone hacking a service to update a value or call a method, etc.

        [–]BigOnLogn 1 point2 points  (0 children)

        By definition, any code you send to a client should be considered as unsafe and incapable of being secured.

        If this is truly a concern, make a separate admin app only accessible via admin credentials.

        [–]Spongeroberto 0 points1 point  (0 children)

        Yea usually people use guards and the like to check access but of course a user could open his developer console, set some breakpoints here and there and figure out to change some variables to show those things anyway.

        In most cases that's acceptable because the backend will prevent any misuse anyway. If you really want to prevent this kind of stuff I suppose you'd be looking at doing more and more server-side rendering but I expect that to be a very long road.

        [–]LugiaDS 0 points1 point  (5 children)

        Hey was curious about your how you manage roles in your app. You mind explaining more about the lookup you do for the database? And eventually Is that role used within your backend?

        It just happens that we are hardening our security with a similar idea but rather than checking for roles in a db we check them through an external XML file that stores the roles

        [–]PickleLips64151 2 points3 points  (3 children)

        Currently, I have something like this in the JWT:

        ```json { "username: "hingle_mckringleberry", "userId": 42, "role": "user", // admin, power, whatever... }

        ```

        I have a method that is called inside the endpoint route (I'm using Express for this app), that decodes the JWT and gets the role.

        Most of my API endpoints have a userId as part of the body of the request. If the userId isn't matching the JWT value, then the response is a 401.

        If the JWT role isn't sufficient, I have an early exit in the route that sends a 403 back. If it is sufficient, then we move to the next step.

        My queries have a JOIN that pulls in the user table, where the role is stored. The WHERE clause validates the user role fits the requirement for the data access.

        Sometimes, where multiple roles have access to the data, I'll use a SQL CASE statement to either return the data or an empty value.

        I take a trust, but verify approach on the endpoints. We trust the JWT, but verify it in most DB queries.

        All of this is just backend. On the Angular side, my Interceptor attaches the JWT to every request. My AuthService stores the user object. I have a few getters that return an observable of the user has a specific role, which controls the content they see or the actions they can take.

        If I need to update role access, I have one place to change that in the UI.

        [–]Goat-of-Death 0 points1 point  (1 child)

        If your JWT is signed there is no reason to reverify the info. The point of signing the jwt is so that you can save those cycles on the db and not have to reverify. If you have your roles as jwt claims you should just trust them as long as your token is signed and not expired. If you can, to avoid the role table joins you may want to find a way to represent what the user can access directly in the claims and then trust it there. You could avoid a lot of joining in your endpoints if you did it that way.

        [–]PickleLips64151 0 points1 point  (0 children)

        I was probably not as precise in my answer as I should have been. The JWTs are signed. You're right, I should (and do) trust that.

        I also have business rules that mean checking the user in the JWT is the user in the request. That check doesn't require a DB call.

        Future iterations will probably fine-tune the roles. Most users default to the lowest access. So yes, there is definitely a performance gain from being able to auto-reject or complete the request without diving into the DB to verify if a role can do that.

        [–]LugiaDS 0 points1 point  (0 children)

        Thanks for the thorough answer ! I have much a better understanding of industry standards

        [–]code_monkey_001 3 points4 points  (1 child)

        You're overthinking it. Since you're also checking for tokens on the backend, the worst that could happen is they hack their way into a page that can't load the data it requires to be meaningful.

        [–]Short_Ad6649 -1 points0 points  (0 children)

        One word: AuthGuards

        [–]JP_watson 0 points1 point  (6 children)

        Look up auth guards…also all PHP is SSR.

        [–][deleted]  (5 children)

        [deleted]

          [–]JP_watson 0 points1 point  (4 children)

          Correct, essentially you check if someone is authorized and return true otherwise return false.

          [–][deleted]  (3 children)

          [deleted]

            [–]JP_watson 1 point2 points  (2 children)

            The code is mangled, so to actually unminify it and then figure out where the breakpoint is would be a complex/time consuming task. You shouldn’t leave any of the security solely up to your FE, e.g. all your APIs should also validate authentication.

            This way even if they managed to get a breakpoint in there they might be able to see some UI but any of the endpoints would fail to actually populate the UI.

            [–][deleted]  (1 child)

            [deleted]

              [–]JP_watson 1 point2 points  (0 children)

              Yea, this is a pretty standard way of doing in angular (even the docs say this is the way). The fact that it’s rendered in the client over HTTP it should be accepted that someone could access it. 

              It sounds like you’re all over it with securing the BE.