You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm currently working on a REST API where I want to have fine-grained control of many different reads and writes to a few resources/routes. At the same time, I also want the API to be accessible both by actual users in our organization, as well as other applications/background processes/daemons.
I learned recently that scopes only make sense for user access, and that for applications, I should be using "app roles". I initially believed I could solely use scopes for representing permissions in a unified manner, so this realization came as a shock to me.
However, trying to handle them both as different types of access on my API leads to quite a bit of code and honestly, I think that these concepts are very low level to expose to someone reading the API code (the fact that scopes and roles can work differently depending on the token type).
So, I contemplated abstracting all of this away into my own concept of "permissions". Instead of explicitly authorizing scopes or roles in any given method, I'd authorize "permissions", and then I'd perform either a scope or a role check in the background depending on the type of the token being passed to the API. With requirements and requirement handlers, I could do this by:
Defining a service/class/helper that maps from a "permission" to a "scope" or "role"
Defining my own custom PermissionsRequirement that stores which permissions are needed for any given action (say, "Reservations.Read" for reservation resources)
Registering a UserPermissionsAuthorizationHandler, that would check whether the current token is a "user token" and, if it is, check whether it has the required scopes related to the permissions I passed by consulting the "permission" -> "scope" service map
Similarly to the above, registering a ApplicationPermissionsAuthorizationHandler, that would check whether the current token is a "application token" and, if it is, check whether it has the required roles related to the permissions I passed by consulting the "permission" -> "roles" service map
Since 3 and 4 are handlers for the same requirement, they would naturally work as an OR between the 2 scenarios:
an user is trying to access -> check the correct scope(s) -> succeed if permission-to-scope mapping exists and the scope is present
an application is trying to access -> check the correct role(s) -> succeed if permission-to-role mapping exists and the role is present
This would provide me with a more centralized means of specifying whether or not any given action is available to users, to applications, or to both, and control them in a more abstract manner.
While I strongly feel this would be much cleaner than trying to shoehorn the existing scopes and roles checks manually somewhere (say, calling HttpContext.ValidateAppRole and HttpContext.VerifyUserHasAnyAcceptedScope like this). I fear I might be "reinventing some wheel" here by creating this whole abstraction and that perhaps there is a simpler, more standard way to go about this.
Do you think is is a sound idea to abstract away this concept of "permissions" in my implementation so I can handle both users with scopes and applications with roles in the same manner, or would you recommend a different approach that keeps the more explicit scope and role checks evident? Is there some existing mechanism that I'm missing that I could leverage to achieve the same results in a more streamlined way? Lastly, would it be advisable to name scopes and roles similarly/identically at all, or should I keep those names different on purpose?
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
I'm currently working on a REST API where I want to have fine-grained control of many different reads and writes to a few resources/routes. At the same time, I also want the API to be accessible both by actual users in our organization, as well as other applications/background processes/daemons.
I learned recently that scopes only make sense for user access, and that for applications, I should be using "app roles". I initially believed I could solely use scopes for representing permissions in a unified manner, so this realization came as a shock to me.
However, trying to handle them both as different types of access on my API leads to quite a bit of code and honestly, I think that these concepts are very low level to expose to someone reading the API code (the fact that scopes and roles can work differently depending on the token type).
So, I contemplated abstracting all of this away into my own concept of "permissions". Instead of explicitly authorizing scopes or roles in any given method, I'd authorize "permissions", and then I'd perform either a scope or a role check in the background depending on the type of the token being passed to the API. With requirements and requirement handlers, I could do this by:
PermissionsRequirement
that stores which permissions are needed for any given action (say, "Reservations.Read" for reservation resources)UserPermissionsAuthorizationHandler
, that would check whether the current token is a "user token" and, if it is, check whether it has the required scopes related to the permissions I passed by consulting the "permission" -> "scope" service mapApplicationPermissionsAuthorizationHandler
, that would check whether the current token is a "application token" and, if it is, check whether it has the required roles related to the permissions I passed by consulting the "permission" -> "roles" service mapSince 3 and 4 are handlers for the same requirement, they would naturally work as an OR between the 2 scenarios:
This would provide me with a more centralized means of specifying whether or not any given action is available to users, to applications, or to both, and control them in a more abstract manner.
While I strongly feel this would be much cleaner than trying to shoehorn the existing scopes and roles checks manually somewhere (say, calling
HttpContext.ValidateAppRole
andHttpContext.VerifyUserHasAnyAcceptedScope
like this). I fear I might be "reinventing some wheel" here by creating this whole abstraction and that perhaps there is a simpler, more standard way to go about this.Do you think is is a sound idea to abstract away this concept of "permissions" in my implementation so I can handle both users with scopes and applications with roles in the same manner, or would you recommend a different approach that keeps the more explicit scope and role checks evident? Is there some existing mechanism that I'm missing that I could leverage to achieve the same results in a more streamlined way? Lastly, would it be advisable to name scopes and roles similarly/identically at all, or should I keep those names different on purpose?
Related:
Beta Was this translation helpful? Give feedback.
All reactions