3
votes

I have created a .NET Core 2.0 API and published it to Azure. I have an API Management (APIM) instance fronting that API and doing all the wonderful things that it does. However, there is one thing I cannot seem to wrap my head around or find any documentation for. Authorization on operations. (Not to be confused with authentication, which I have working very well).

My API is a simple RESTful service with CRUD actions. Let's take a read operation for example:

GET /api/owner/{ownerid}/thing/{thingid}

In this case, what I want to be able to do is to grant users permissions to READ THINGS within a specific OWNER. The same user may not have read permissions with a different owner. If the user has permissions, 200 OK; otherwise, 403 Forbidden.

Leaving this completely carte blanche, what are some suggestions for implementing this? I assume an inbound policy for each operation within APIM is where the action will take place? If so, how?

Update 1

I was informed of the possibility of using the same validate-jwt policy at the individual operation levels to append to the validate-jwt policy at the root. The idea is that the root policy validates that the user is authenticated while the operation policy checks for specific claims. This appears to work well, but is that the correct method, or just a hack?

Update 2

For the validate-jwt option to work, the permission model would need to align well with roles and groups; otherwise, it's just as much work as setting up your own custom database wherein at least you benefit from your own rules. In the end, I put the permissions in an Azure Storage Account table (any database will do) and used a send-request (with appropriate caching) to gather permissions based on the current operation and user. It works well, but "feels wrong". I am happy to share details to anyone who wants. In the meantime, I'll leave this open for now in case someone has a better idea.

2

2 Answers

0
votes

Ultimately the only way to do so is by using policies at operation level. you can use validate-jwt to check for specific claims, you can check some other credentials that are passed to you as a part of request. Or you can use send-request to call some other service and ask for user permissions. In APIM itself there is no place to store any user related data besides some basic info, thus it is required for such authorization information to come from outside of APIM.

0
votes

In the end it appears that there is no built-in solution. Rolling your own permission model and then validating it yourself is the way to go.

However...

This can still be done in APIM. As I mentioned in my second update, I was able to make a custom solution work. The way it was done was to use an inbound policy at the "all operations" level to retrieve permissions. (A caching mechanism was used so as not to retrieve the permissions on every single call.) Then, each operation determines if the user has permission to that specific operation based on the parameters that were passed in. (That is also cached.)

The result is that the root API has no authentication or authorization built-in, but APIM does and the appropriate behavior is observed.

Still, the preference would be an RBAC approach. For example, imagine the individual operations being seen as services as in this role definition:

{
  "Name": "{rolename}",
  "Id": "{roleid}",
  "IsCustom": true,
  "Description": "{roledescription}",
  "Actions":  [
    "GET {myapi}/owner/{ownerid}/*",
    "POST {myapi}/owner/{ownerid}/*",
  ],
  "NotActions": [],
  "DataActions": [],
  "NotDataActions": [],
  "AssignableScopes": [
    "/subscriptions/{subscriptionid}"
  ]
}

If that were possible, we could create roles, assign them to users/groups at the subscription level, then have the claims automatically passed to APIM where they can be evaluated like any other claim.