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?
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.