Restrict access to apis by product and HTTP method

Hi,

I have a use case where I have to restrict access to our apis using api path and http method

Eg I have the below endpoints

GET /v1/organizations

POST /v1/organizations

DELETE /v1/organizations

I need to restrict access by both endpoint and http method. Some users should have access to only GET and some users should have only to POST while some will have to all the HTTP methods

We are using apikey authentication for the apis. Is there a way I can achieve the above using apikey validation ?

I see I can add specific endpoint to the product but the product doesn't allow to add http methods

Appreciate your help

Thanks

Ram

Solved Solved
0 9 2,169
2 ACCEPTED SOLUTIONS

Hi Ram,

The products do not allow you to restrict the HTTP methods per endpoint. You would have to do this within the API Proxy.

One approach would be to add attributes to the product to define the allowed methods and then enforce these after the API key is validated. This could potentially also be done in a shared flow if this is a common functionality.

View solution in original post

Not applicable

There is no inbuilt option for the method. You can specify allowed methods in the developer app or product custom attributes. Later in api flow fetch and verify. If ot matching with methods in attributes it will throw error.

View solution in original post

9 REPLIES 9

Hi Ram,

The products do not allow you to restrict the HTTP methods per endpoint. You would have to do this within the API Proxy.

One approach would be to add attributes to the product to define the allowed methods and then enforce these after the API key is validated. This could potentially also be done in a shared flow if this is a common functionality.

Yes, if you wanted to do it this way, I can suggest using a single custom attribute on the API Product, which contains a JSON map that describes the tuples of {GET, POST, PUT, DELETE. etc} vs the actual path.

Then use a JS callout to deserialize that JSON and find the match of request.verb and proxy.pathsuffix .

Thank you @daniel, @Priyadarshini and @dino for the solution. I understand that there is no OOB solution for this and would have to implement a custom logic

Not applicable

There is no inbuilt option for the method. You can specify allowed methods in the developer app or product custom attributes. Later in api flow fetch and verify. If ot matching with methods in attributes it will throw error.

Hi,
Access can be limited to HTTP Methods by using the custom attributes in products.

Rohit_Kancharla_0-1657803942852.png

 

<Step>
    <Name>Raise-Fault-1</Name>
    <Condition>(request.verb != apiproduct.Allowed-Methods)</Condition>
</Step>

 

 

 

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<RaiseFault async="false" continueOnError="false" enabled="true" name="Raise-Fault-1">
    <DisplayName>Raise Fault-1</DisplayName>
    <Properties/>
    <FaultResponse>
        <Set>
            <Headers/>
            <Payload contentType="application/json">{"error":"Not allowed to perform this action"}</Payload>
            <StatusCode>405</StatusCode>
            <ReasonPhrase>Method not Allowed</ReasonPhrase>
        </Set>
    </FaultResponse>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</RaiseFault>

 

 

yes! Great suggestion. and... if your Allowed-Methods is a list containing multiple distinct methods, you'd be able to use a JavaRegex operator there, instead of the Equals operator. This will work great. 

Hi @dchiesa1 ,

Can you please provide an example for this?

Whoops - I misspoke. It is not possible to specify a variable on the right hand side of a JavaRegex operator.

This gets rejected by validation:

 

   <Condition>request.verb JavaRegex apiproduct.Allowed-Methods-Regex</Condition>

 

The right hand side must be a constant string, which is compiled at the time the proxy gets deployed. It should look like this:

 

  <Condition>request.verb JavaRegex "^(GET|POST)$"</Condition>

 

You CAN implement a comparison of the verb against a list that is contained in a context variable. But you cannot do it directly within a condition. For that you need an additional Policy, like a JS policy. You could do something like this:

 

var allowedList = context.getVariable('apiproduct.allowed-method-list'); // eg, "GET, POST"
var actualVerb = context.getVariable('request.verb'); // eg, "PUT"

function isAllowed(verb) {
  var allowedVerbs = allowedList.split(',').map(function(x) { return x.trim();});
  return allowedVerbs.find(function(x) { return x == verb; });
}

if ( ! isAllowed(actualVerb)) {
  throw new Error('That method is not allowed');
  // proxy will enter fault status, as with RaiseFault
}

 

And so rather than a RaiseFault with a Condition in the flow, you would just insert this JS into the flow. Call if JS-Check-Verb , or something like that.

 

<Step>
  <Name>JS-Check-Verb</Name>
  <!-- will throw a fault if the verb is not on the allowed list -->
</Step>

 

Keep in mind, in Apigee X/hybrid, there is the very cool Operations configuration on the API Product, and you can configure verb+path pairs for all of the API proxies. And of course you can use a wildcard path like "/*". And if you use that, then a VerifyAPIKey or VerifyAccessToken policy in your flow will do this check implicitly for you. You would not need to resort to the manual check in a JavaScript policy.

Hi @dchiesa1 ,

Works for me.

Thank you!