Conditional Step flow for API Proxy

Hi

We have a use-case where on the basis of request query parameter value "true" we want to execute the Service CallOut policy and pass the request or value "false" we want to get the cookies from the request and check if one of the cookies is present in the request then pass through without executing the Service CallOut policy else stop the request.

How we can achieve this in best possible manner ?

Thanks

Gaurav

----

EDIT

Basically we will have two types of apiKey (one system generated and other custom api key) that will come in request

Then we need to check if apiKey is custom(means it has some prefix like internal_apiKey) then we have two scenarios

1. If Request contains some set of cookies then pass through else stop the request saying Invalid Credentials

2. Else If Request contains user credentials (username and password), then execute the Service CallOut and get the cookies and then pass the request and if Service CallOut fails with status code other than 200 then also stop the request saying Invalid Credentials.

And then if apiKey is external (means it has no internal_apiKey) then it needs to get the access token from the request and execute the Service CallOut (which is different from above Service CallOut) and get the cookies and then pass the request and if Service CallOut fails with status code other than 200 then also stop the request saying Invalid Credentials.

Last scenario where we have access_token in the request is already in place.

Solved Solved
0 13 2,088
1 ACCEPTED SOLUTION

Guarav, I think you want something like this:

  <PreFlow name='PreFlow'>
    <Request>
      <Step>
        <!-- this sets userAuthenticationResponse to hold the authentication response-->
        <Name>SC-AuthenticateUser</Name>
        <Condition>request.formparam.username != null AND request.formparam.password != null</Condition>
      </Step>
      <Step>
        <!-- this sets context variables like requestCookie.NAME, from the SC Response -->
        <Name>ExtractVariables-GetUserCookies</Name>
        <Condition>userAuthenticationResponse != null</Condition>
      </Step>
      <Step>
        <!-- this sets context variables like requestCookie.NAME -->
        <Name>JS-ParseInboundCookies</Name>
        <Condition>userAuthenticationResponse != null</Condition>
      </Step>
      <Step>
        <!-- send back a fault if the expected cookie is not present -->
        <Name>RF-MissingCookies-UserMustAuthenticate</Name>
        <Condition>requestCookie.MY_COOKIE_NAME = null</Condition>
      </Step>
    </Request>
    <Response/>
  </PreFlow>


I have left the policies for you to implement. But that's the basic flow, I think.

First check for user credentials, and if present, then make the ServiceCallout.

Then extract cookies from that response.

If there is no response (which means there was no user credentials) then look for cookies in the inbound request, and parse them.

If no cookies have been passed, or received from the ServiceCallout, then send back a fault telling the user to authenticate.

View solution in original post

13 REPLIES 13

Not applicable

@GAURAV can you help me understand if this is what you are trying to achieve :

- If in the request a query parameter is present then execute a service callout to external system and check if in the response a specific cookie is present.

- If cookie present then follow through

- If cookie doesn't exist then stop the request

- If in the request a query parameter is not present than stop the request.

@GAURAV , As you said, it can be achieved by conditional flows. It should be straight froward. Have you tried something ? Do you see an error ? Are you stuck with some issue ?

@rakshith@apigee.com

@Anil Sagar

Actually we were discussing the use case so couldn't respond , so now we have the use case in place.

Basically we will have two types of apiKey (one system generated and other custom api key) that will come in request

Then we need to check if apiKey is custom(means it has some prefix like internal_apiKey) then we have two scenarios

1. If Request contains some set of cookies then pass through else stop the request saying Invalid Credentials

2. Else If Request contains user credentials (username and password), then execute the Service CallOut and get the cookies and then pass the request and if Service CallOut fails with status code other than 200 then also stop the request saying Invalid Credentials.

And then if apiKey is external (means it has no internal_apiKey) then it needs to get the access token from the request and execute the Service CallOut (which is different from above Service CallOut) and get the cookies and then pass the request and if Service CallOut fails with status code other than 200 then also stop the request saying Invalid Credentials.

Last scenario where we have access_token in the request is already in place. Attaching is the proxy bundle

We want to know the best approach to achieve this

Thanks

Guarav, I think you want something like this:

  <PreFlow name='PreFlow'>
    <Request>
      <Step>
        <!-- this sets userAuthenticationResponse to hold the authentication response-->
        <Name>SC-AuthenticateUser</Name>
        <Condition>request.formparam.username != null AND request.formparam.password != null</Condition>
      </Step>
      <Step>
        <!-- this sets context variables like requestCookie.NAME, from the SC Response -->
        <Name>ExtractVariables-GetUserCookies</Name>
        <Condition>userAuthenticationResponse != null</Condition>
      </Step>
      <Step>
        <!-- this sets context variables like requestCookie.NAME -->
        <Name>JS-ParseInboundCookies</Name>
        <Condition>userAuthenticationResponse != null</Condition>
      </Step>
      <Step>
        <!-- send back a fault if the expected cookie is not present -->
        <Name>RF-MissingCookies-UserMustAuthenticate</Name>
        <Condition>requestCookie.MY_COOKIE_NAME = null</Condition>
      </Step>
    </Request>
    <Response/>
  </PreFlow>


I have left the policies for you to implement. But that's the basic flow, I think.

First check for user credentials, and if present, then make the ServiceCallout.

Then extract cookies from that response.

If there is no response (which means there was no user credentials) then look for cookies in the inbound request, and parse them.

If no cookies have been passed, or received from the ServiceCallout, then send back a fault telling the user to authenticate.

Thanks @Dino for your response and I made the below flow based on that and the requirements.

Please validate the same

Now I want to achieve the first condition which determines which route (set of steps should be followed next )

if (apiKey contains "internal_")

Is there a concept of nested STEPS based on CONDITION to achieve this ?

if (request.queryparam.apiKey contains "internal_") {

   if (request.queryparam.username != null AND request.queryparam.password != null) {
     Prepare Request (Required params for SC below)     
     Authenticate System User (SC)     
     CookieSetter (JS - put the cookies in the request from SC)   

   }   
   ParseInboundCookies (JS)   
   Raise Fault(RF-request contains invalid cookies)

}

else 

{   //what is happening right now (in attached proxy bundle)   	
	Prepare Request (Required params for SC below)   
	AuthenticateUser (SC)   
	ParseHttpStatus (AM - get https status)   
	CookieSetter (JS -put cookies in request from SC)   
	Raise-Fault   (RF-if http status above is not 200)

}

Hi GUARAV, today there is no concept of nested steps. We are working on a feature that would enable this, though, if that makes you feel any better.

However, you can combine Conditionals with boolean logic.

<Condition>request.formparam.username != null AND request.formparam.password != null AND request.queryparam.apiKey ~~ "^internal_"</Condition>

Hi @Dino

When the NESTED steps feature will come ? any tentative version of APIGEE ?

Does this request.queryparam.apiKey ~~ "^internal_" same as request.queryparam.apiKey contains "internal_"

Also do I need to add this condition for every STEP as this holds true for all the STEPS under top if condition in code above ?

Sorry, I do not have a release date or version. We're working on it.

The ~~ syntax uses a Regular Expression. It is not "contains" but more like StartsWith .

Yes, you need to add the test for the apikey, to every step for which it is appropriate.

Hi @Dino

Yeah actually I want apiKey starting with "internal_" so it seems that below will work

request.queryparam.apiKey ~~ "^internal_" ?

Hi @Dino

How can I check in Raise Fault Condition if the specific cookies are present in header or not

Below code doesn't work, if I provide only request.header.cookie.1, it works but i need to check the name of the cookie also

      <Step>
        <!-- send back a fault if the expected cookie is not present -->
        <Name>RF-MissingCookies-UserMustAuthenticate</Name>
        <Condition>request.header.cookie.1.AUTHN_TOKEN == NULL</Condition>
      </Step>

As you can see in the attached trace, request.header.cookie.1 is the name of the cookie and value has the AUTHN_TOKEN.

Also attaching the JS file which I am using to parse the cookies from SC and set it in request.

test-cookies.zip

Hi @Dino

I am able to get through above issue by naming the cookies appropriately and using the condition below

<Condition>request.header.cookie.AUTHN_TOKEN == null AND request.queryparam.apikey =| "internal_"</Condition>

Now how can I get the reverse of the condition of apikey above?

Currently it checks if apikey starts with "internal_" but now i want if apikey doesn't start with "internal_" ?

Conditions allow boolean logic.

request.header.cookie.AUTHN_TOKEN == null AND NOT(request.queryparam.apikey =| "internal_")

See the documentation.

Also, ask new questions in new questions. Do not ask questions in answers to your own questions - nobody sees them there. I'm going to close this question now.