123
Views
5
Comments
Solved
Managing Scope Authorization Mappings for Exposed REST APIs

Okay so here is a potentially weird one, so I am going to attempt to provide as much backstory as possible. 

I am attempting to expose a series of REST APIs. These APIs are going to be secure, both Authenticated and Authorized, using OAuth tokens from the Azure AD v2 endpoints. Because these tokens are signed JWTs, it is relatively easy to accomplish the Authentication portion of things. Where things get dicey for me is authorization.

Generally, my understanding is that scopes in the scp claim of one of these tokens is what you use for deciding what the bearer of the token can and cannot do within your API. I have chosen a model in which access is denied for all REST endpoints unless the token has a scope that is given permission to use that REST action. In order to make maintenance easier, my plan was to build a centralized tool which maintains information about all the exposed REST APIs in a given environment.

A REST API has scopes associated with it. Scopes are then associated in some way with the actions in that REST API. I thought you could do the latter in a couple different ways, neither of which I seem to be able to figure out:

1. Permissions are saved as a connection between scope and the permitted action

This one would be lovely to implement since you can use OutDoc to generate a list of the actions in an exposed REST API to make setup and maintenance easier on the end user. Additionally, it would relieve the pain of needing to parse the path of an incoming request. However, there is a problem with this approach:

I would really like to avoid asking the developers of APIs at my organization to put an action in every REST action to determine the permission of the incoming request. I would rather the whole scope-checking scheme be handled in the OnAuthentication event as part of the token validation step. However, it doesn't seem possible to get information from the platform as to what the target action is when you're in the OnAuthentication filter. When using the forge component ActionInfo, all you can see is that you're in the OnAuthentication action. All you really seem to be left with is using the path and the HTTP verb of the incoming request to figure out what the request is trying to do. Which brings us to option 2.

2. Permissions are saved as a connection between scope, path, and HTTP verb

The information you can get in the OnAuthentication step is whatever info is present in the headers of the request. So theoretically you could have the developers/administrators maintain API security by saving permissions in a format like the following:

scope     GET     /path/{attribute}

This, however, would be much more difficult to maintain than a simple scope:action pairing since the HTTP verb and the path are sort of built into the action itself. Additionally, there is absolutely no way to automatically retrieve the path and verb information for actions in an exposed REST API (that I know of) so there's no way to generate these configurations to make things easier on the administrators. And then there's the issue of needing to define paths as regular expressions so you are certain you're checking the correct permission for the correct endpoint. Basically this route is possible, but it is a maintenance nightmare.

So what am I asking?

Am I just thinking about this in the completely incorrect way? Has anyone else out there had to work through this issue? Is there actually a way to get the intended action for a request when you are in the OnAuthentication handler of a request? I am running out of ideas, OutSystems friends, and I am sending up the Bat Signal. Looking forward to responses. Thanks all. 

2021-10-09 07-57-44
Stefan Weber
 
MVP
Solution

Hi Grayson. Yes the Verb, Path options seems like the most simple approach. Your are of course right that maintaining the routes along with it scopes can be cumbersome. I would create a separate "management" application where you configure all routes and scopes and expose a validation service action which can be included in the OnAuthentication flow (note that in a service action you do not have access to the original url and verb, so the service action would take the path, verb and token as an input). The service action would decode the jwt to get the scopes, checks if path, verb and scopes matches and returns a boolean IsValid result along with an error message in case of false). Potentially you can combine everything in a single service action including token signature validation or identity provider provider introspection.

2021-10-09 07-57-44
Stefan Weber
 
MVP

Hi,

the easiest way to get the resource path requested in the OnAuthentication handler is to use the the following actions from the HttpRequestHandlerModule

* GetUrlMethod - This one returns the HTTP Verb

* GetUrl - Returns the absolute Uri requested (https://<your env domain>/......)

* GetRawUrl - Returns the relative requested Url (/<your module>/rest/....)

Personal note: I only have one project running where we a exposing quite a complex REST API with scope validation and authorization. In the early phase of the project, we decided to offload openid token validation and scope checking to a frontend API Gateway. This also allowed us to provide a more complete OpenAPI specification including documentation for necessary scopes. (but that was not the primary reason, but rather things like rate limit control, json transformation and better usage tracking).

Hope that helps,

Stefan


2018-01-05 02-53-30
Grayson Udstrand

Hey Stefan, thanks for the detailed and helpful response. I am checking in to see if we can use an API Gateway tool as well but I am guessing I will still need to implement scope management myself. I take it from your response that you would probably recommend doing so by using the verb/path option I outlined in my original post? If you had any other suggestions for implementing this, I am all ears. 

2021-10-09 07-57-44
Stefan Weber
 
MVP
Solution

Hi Grayson. Yes the Verb, Path options seems like the most simple approach. Your are of course right that maintaining the routes along with it scopes can be cumbersome. I would create a separate "management" application where you configure all routes and scopes and expose a validation service action which can be included in the OnAuthentication flow (note that in a service action you do not have access to the original url and verb, so the service action would take the path, verb and token as an input). The service action would decode the jwt to get the scopes, checks if path, verb and scopes matches and returns a boolean IsValid result along with an error message in case of false). Potentially you can combine everything in a single service action including token signature validation or identity provider provider introspection.

2018-01-05 02-53-30
Grayson Udstrand

Thanks, Stefan! And you read my mind on the central management tool to make things easier on everyone. This certainly seems like a tool that could have useful applications if it were put on the forge. I am a little surprised that something like this hasn't appeared to come up before anywhere on the forums, either. 

Last question, is there some reason you would favor a Service action over a Server action for the validator in this case? 

2021-10-09 07-57-44
Stefan Weber
 
MVP

You are welcome. I favor service actions across applications to minimize or eleminate strong coupling. With server actions you would have to republish and redeploy to environments with every change you make to the management application. Since i assume that your management application, including the validation service, will be added to multiple other applications it is a good idea to loosley couple them to prevent republishing and redeploying a large set of application just because you added a single if condition somewhere :-)

Community GuidelinesBe kind and respectful, give credit to the original source of content, and search for duplicates before posting.