Search code examples
httpsapigee

Requiring an API call to use HTTPS with Apigee


I'm building a proxy using Apigee that transmits sensitive data. I need to ensure that clients of this API use HTTPS.

I've coded a Raise Fault policy that does something like this

proxies/default.xml

<PreFlow name="PreFlow">
    <Request>
        <Step>
            <FaultRules/>
            <Name>Require-HTTPS</Name>
            <Condition>request.scheme != "https"</Condition>
        </Step>
    </Request>
    <Response/>
</PreFlow>

policies/Require-HTTPS.xml

<RaiseFault async="false" continueOnError="false" enabled="true" name="Require-HTTPS">
<DisplayName>Require-HTTPS</DisplayName>
<FaultRules/>
<Properties/>
<FaultResponse>
    <Set>
        <Headers/>
        <Payload contentType="application/json">\{ 
"status" : 400,            
"message" : "Sensitive transactions may only be executed over HTTPS",
}
      </Payload>
        <StatusCode>400</StatusCode>
        <ReasonPhrase>Requires HTTPS</ReasonPhrase>
    </Set>
</FaultResponse>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</RaiseFault>

The problem is, the fault is always raised, whether I use HTTP or HTTPS to access. I can see in the debugging console that the condition in proxies.xml always resolves to true, whether I use HTTP or HTTPS to access the API. In fact, the request.scheme always seems to be HTTP.

However, I do see the following header using HTTPS access that's not present using HTTP

X-Forwarded-Proto :     https

Can I depend on this header to enforce HTTPS only access to my API? Or is there some other recommended way to do this?


Solution

  • You might try detecting the virtual host rather than the scheme by using the virtualhost.name variable (default or secure).

    However, I suggest you create a two proxies -- one for https and one for http. This will remove the possibility of a consumer slipping past your conditional roadblock. Click on the word "default" under Proxy to edit the entire proxy file and scroll down to the HTTPProxyConnection

    <HTTPProxyConnection>
        <BasePath>/testme</BasePath>
        <VirtualHost>default</VirtualHost>
        <VirtualHost>secure</VirtualHost>
    </HTTPProxyConnection>
    

    Just remove the VirtualHost for default and the consumer will no longer be able to connect using https. I beleive you can then create a second API with the same path, only then remove "secure" and create a RasieFault without a condition. Worst case, you can rely on the Apigee error if you just disable default in your API.