How to prevent clickjacking on Apigee edge?

Not applicable

I have created an action message as below and attached it to Target Endpoint's preFlow but I am still able to add our api proxy url calls into an iframe. May I know what is the right way to do this? Thanks in advance. I am totally new to Apigee.

<AssignMessage async="false" continueOnError="false" enabled="true" name="add-cors">
  <DisplayName>Add CORS</DisplayName>
  <FaultRules/>
  <Properties/>
  <Add>
    <Headers>
      <Header name="X-Frame-Options">SAMEORIGIN</Header>
    </Headers>
  </Add>
  <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
  <AssignTo createNew="false" transport="https" type="response"/>
</AssignMessage>
2 5 419
5 REPLIES 5

The image that depicts the flows is:

6966-proxy-endpoints.png

As you can see there are 4 combinations. In the order in which they execute, they are:

  1. proxy request
  2. target request
  3. target response
  4. proxy response

But it's not so simple. In Apigee Edge the proxy and the target each have a preflow, zero or more "conditional flows", and a "postflow". They execute in that order. Therefore each of the above 4 combinations is really 3, giving 12 attachment points in total. The order is like this:

  1. proxy request
    1. preflow
    2. conditional flow
    3. postflow
  2. target request
    1. preflow
    2. conditional flow
    3. postflow
  3. target response
    1. preflow
    2. conditional
    3. postflow
  4. proxy response
    1. preflow
    2. conditional
    3. postflow

You said you inserted your AssignMessage policy in the preflow of the target. But you didn't specify whether it was the Request preflow or the Response preflow. Because of that we can't say whether it should work or not. But I guess the reason why it's not working is because you attached it to the request preflow.

If you assign to the response in the target REQUEST preflow (phase 2.1), you are assigning to an object (the response) before the target request is made. When Apigee Edge sends the target request and receives the response (phase 3), that target response object is guaranteed to be over-written. Anything - headers body statuscode - you've assigned in the target request preflow will vanish.

I think what you probably want is to attach your AssignMessage policy is the proxy endpoint (not the target endpoint), in the RESPONSE. Either the preflow (4.1) or the postflow (4.3), probably doesn't matter. That says "to the response I got from the target endpoint, I want to add a header, x-frame-options. "

Makes sense?

Hi Dino,

Thanks for your detailed explanation. I am able to further understand the call flow for Apigee's proxy now.

I had tried to attach it at proxy response preflow and postflow but I am still able to include our apigee proxy in an iframe.

I just tried it. It works for me.
I can add a header like this:

<AssignMessage name='AM-Response3'>
  <Set>
    <Headers>
      <Header name='X-Frame-Options'>ALLOW-FROM https://DinoChiesa.github.io</Header>;
    </Headers>
     ...
   </Set>
  <AssignTo createNew='false' transport='http' type='response'/>
</AssignMessage>

...and the Chrome browser respects that header and refuses to display the content returned from the Apigee Edge browser, in an iframe.

It works just as expected.

BTW I think you want this:

 <AssignTo createNew="false" transport="http" type="response"/>

and not this:

 <AssignTo createNew="false" transport="https" type="response"/>

Actually that "transport" thing is a relic, and shouldn't even be there. Not sure if it will make a difference to your AssignMessage or not. Try and see.

I have tried added the following at proxy-endpoints preflow response as well as postflow response but i am still getting the page loded into my iframe with my api key error message (there's a verify-api-key) function tagged at proxy-endpoints preflow. I had tried to remove this verify-api-key function and include only the CORS actionmessage but to no avail as it got passed through to my backend api server to display error within the iframe.

I understood your statement above mentioning that the header was supposed to be set when responding to the client, but I am not sure what I am doing wrong here now.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage name="add-cors">
<Set>
<Headers>
<Header name="X-Frame-Options">ALLOW-FROM https://www.tst.com</Header>; </Headers> </Set> <AssignTo createNew="false" type="response"/> </AssignMessage>

6973-clickjack-apigee.png

Hi @Kevin Lim -- If you test the call via cURL rather than your browser, you should be able to see whether the header is correctly being added.

Also, you mention an error message -- you probably would need to add the X-Frame-Options header in your fault rules for the error message to get the header. Unfortunately fault rules do not show up in the flow list in the UI -- you'll need to add the XML to the TargetEndpoint.

In the Target Endpoints section in the UI, click on the line that says "prod" (looking at your picture above) -- you'll see the entire TargetEndpoint file.

Then you'll probably want to add a default fault rule like this (see https://docs.apigee.com/api-platform/fundamentals/fault-handling#creatingfaultrules-creatingadefault...

<DefaultFaultRule name="AddXFrameOptions">
  <Step>
    <Name>AddXFrameOptions</Name>
  </Step>
  <AlwaysEnforce>true</AlwaysEnforce>
</DefaultFaultRule>

That AddXFrameOptions step (policy) would be an AssignMessage similar to the one you showed above.