StreetCarts: Tweaking Products to recognize paths and verbs

1342-1319-elcubodecuba.jpg

We’re making good progress on StreetCarts, the API for food cart connoisseurs. If you're unfamiliar with what we're up to, checkout previous articles in the Related Articles list to the right.

In this article we write about a specific technique we used for restricting access to resources by request verb and path. As we mention below, we learned about this techique right here on the Community!

We'd love to get feedback from other Edge developer's who've used this technique, or who found other solutions to the same problem or have thoughts about it one way or the other. We found this technique to be convenient and useful; however, maybe we're overlooking something? Let us know!

Early problem: Multiple products with identical resource paths and proxies

From the start, we knew we wanted to use Products to restrict access to resources — in this way, we could package our APIs to provide multiple levels of service and/or possibly monetization options to developers.

For example, we created one Product geared for apps used by unregistered, public users so that such users could do basic things like look for food carts and view menus. It mostly allows read-access to resources, like this:

GET /v1/streetcarts/foodcarts/{cartId}

We have another Product for apps that a cart owner might use to add and update their food cart information. We imagined these apps would require registration/authentication to use and would allow full CRUD on resources, like this:

PUT /v1/streetcarts/foodcarts/{cartId} -d {'name':'The Grilled Cheese Grill'}

But we quickly discovered that, by default, Products only look at resource path suffixes when deciding whether or not to allow an API request to go through. So, we wondered how could we distinguish between these two APIs in multiple products? Their resource path suffixes are identical. The only real difference is the request verb.

Apigee Community to the rescue

What did we do? We searched the Apigee Community! And we found an article posted by Steve Richardson aptly titled “How to restrict API Resources by their full path and verb”.

We decided to try out Steve’s technique of setting the flow.resource.name variable in a JavaScript policy so that it includes the request verb and path. The policy is called just before token validation takes place. Then, when the Product logic executes, it uses the value of this variable to make the resource path comparison.

This technique gives us the ability to distinguish in Products whether an API request for a resource is for a GET, PUT, POST, or DELETE, giving us the finer-grained control we were seeking.

Let’s say the client wants to get a menu. The API looks like this:

GET /v1/streetcarts/menus/<menuId>

In this case, the flow.resource.name variable is set as follows in the JavaScript policy...

/GET/v1/streetcarts/menus/*

…which matches a resource we put in both the "public," read-only product and the "restricted" product, allowing the call to go through in either case after API key validation.

However, when PUT is called on the very same resource, the JavaScript policy sets the flow variable as follows...

/PUT/v1/streetcarts/menus/*

…and this path is only added to the “restricted” product (for cart owners). An app that only has the “public” API key cannot do a PUT to this API and Edge returns an error in that case.

To finish up, here’s what our “restricted” product looks like as of today. You can see we’ve started adding apiResources for the different kinds of operations we want apps possessing keys associated with this product to be able to do.

{  "apiResources": 
  [  "/GET/v1/streetcarts/menus/*/items/*",  
     "/POST/v1/streetcarts/menus/",  
     "/GET/v1/streetcarts/foodcarts/*/menus",  
     "/GET/v1/streetcarts/foodcarts/*",  
     "/GET/v1/streetcarts/users/",  
     "/POST/v1/streetcarts/users",  
     "/PUT/v1/streetcarts/menus/*",  
     "/POST/v1/streetcarts/accesstoken",  
     "/POST/v1/streetcarts/users/*",  
     "/DELETE/v1/streetcarts/menus/",  
     "/GET/v1/streetcarts/users/*"  
   ],  
   "approvalType" : "auto",  
   "attributes" : [ ],  
   "description" : "The API Product for street cart owners",  
   "displayName" : "SC-OWNER-PRODUCT",  
   "environments" : [ "test", "prod" ],  
   "name" : "sc-owner-product",  
   "proxies" : 
      ["users", "reviews", "menus", "items", "foodcarts", "accesstoken"],  
   "quota" : "",  
   "quotaInterval" : "",  
   "quotaTimeUnit" : "",  
   "scopes" : [  ]} 
Comments
bhatikuldeep
Silver 2
Silver 2

@wwitman thanks for sharing this, I wanted to check referred article - https://community.apigee.com/content/kbentry/2514/how-to-restrict-api-resources-by-their-full-path-a..., but I get

Access Denied

We're sorry, but you do not have permission to do the activity you attempted. If you believe this to be in error, please contact the site administrator(s).

does it work for you?

willwitman
Staff

Hi @Kuldeep Bhati - Apparently this article was removed from the public site. Possibly because the technique was not considered to be a best practice. I'll try to find out. Sorry for the confusion!

bhatikuldeep
Silver 2
Silver 2

No problem, thanks @wwitman!

kirill-ageev
New Member

@Will Witman So what's the best practice now? Thanks.

Version history
Last update:
‎11-11-2015 11:29 AM
Updated by: