codemation / easyauth

Create a centralized Authentication and Authorization token server. Easily secure FastAPI endpoints based on Users, Groups, Roles or Permissions with very little database usage.
https://easyauth.readthedocs.io/en/latest/
MIT License
553 stars 52 forks source link

Action not being deleted from "Roles_to_Actions" table in database #80

Closed pedrocavadas closed 1 year ago

pedrocavadas commented 1 year ago

While testing my EasyAuth Client, I came across an odd behavior. Basically, when I delete an action via web GUI, the database does not get correctly updated, allowing for methods that depend on this action for permission to continue working. Here are the steps I followed inside the GUI:

  1. Create an action, let's say "TEST_ACTION";
  2. Create a role "test_role" and assign "TEST_ACTION" to it;
  3. Create a group "test_group" and assign "test_role" to it;
  4. Create a service "test_service" and assign "test_group" to it;
  5. Finally, generate a token for "test_service".

In my Client code, I defined a generic POST method to test if the token worked correctly, defining "TEST_ACTION" as the required permission. Then, I made a request to this method, sending the token as header, and everything worked perfectly.

After that, my next test was to force an "Unauthorized" error on this request by deleting "TEST_ACTION", so the token wouldn't have permission, and this is where I noticed the strange behavior: the request still worked. Have in mind that I only used the GUI to create and delete "TEST_ACTION", so I'm not sure if this behavior would repeat itself if I used only the default HTTP requests that are created when you instantiate the EasyAuth Server.

I checked the database file to see what was going on, and this is what I gathered: when I delete the action, it gets correctly removed from "Actions" table. However, this does not happen on "Roles_to_Actions" table, as the line "test_role | TEST_ACTION" continues there. So, when the program accesses this table to check if "test_role" has the necessary permissions, it allows the method to work. I tried restarting both Server and Client, but the results were the same.

codemation commented 1 year ago

Hello @pedrocavadas , based on the steps and behavior you described, I actually think this is related to how JWT tokens work. If you inspect the JWT token, you will notice that is is comprised of 3 base64 encoded strings separated by a .

The middle string, if decoded contains a human readable mapping of the user & its' permissions(groups, roles, action). Also included here is the expiration date of the token and the tokens id. The token and its permissions, once created, are valid as long as 1) the token has not expired, 2) the signature of the token has not changed(i.e manually modifying token), or 3) the server side RSA key used to validate the token has changed.

Service account tokens are given a much longer expiration date. So simply removing an action will not disable the existing token which is created with the permissions the user had at the point in time the token was created. The same can / should also be considered when adding actions to a role; an old token will not inherit newly created actions until a token is reissued.

Tokens which have not yet expired can be "invalidated" by visiting the "tokens" page in the admin. Issued tokensID's are tracked and can be invalidated so the token no longer functions in an EasyAuth protected endpoint.

Since service account tokens are manually generated, automatically invalidating a token after permissions changes is purposely avoided to avoid breaking existing remaining functionality.

pedrocavadas commented 1 year ago

I see, so that's an intended behavior. I actually thought that the token retaining information about the permissions could be the case, but since I was not sure, I came here to ask. Thank you so much.