Hi Community,
I am using Verify API Key Policy and everything is working if I made a request using curl.
e.g.:
curl -X GET "https://myapi.net/api/v1/resource/id" -H "accept: application/fhir+json" -H "x-api-key: apikey"
And for this request I can see on Apigee trace tool the follow headers :
Request Headers |
||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
However when I make the same request from my api using Portals it's not working. I'm using a swagger:
From this request I got the follow on trace:
Request Received from ClientOPTIONS /api/v1/resource/id | |
---|---|
Request Headers | |
Accept | text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 |
Accept-Encoding | gzip,deflate,br |
Accept-Language | en-US,en;q=0.5 |
Access-Control-Request-Headers | x-api-key |
Access-Control-Request-Method | GET |
Host | myapi.net |
Origin | https://developers.portal.net |
User-Agent | Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0 |
X-Forwarded-For | xxx.xxx.xxx.xxx |
X-Forwarded-Port | 443 |
X-Forwarded-Proto | https |
I've tested the same swagger yaml file using swaggerhub.com to make the request and from there its working fine.
From trace and making the request using swaggerhub.com I've got the follow:
Request Received from ClientGET /api/v1/resource/id |
Response Sent to Client200 | ||||||||||||||||||||||||||
Request Headers |
Response Headers | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
I've noticed that when I made the request from curl, and swaggerhub I can see the x-api-key header on request but not by portals.
Thanks in advance if you can help me. And if you need more details, please just ask. Let me know if you guys need me to paste some xml configuration from my proxy api.
Thank you
yes, this is a CORS issue. Thanks for the detailed explanation, very helpful.
You wrote:
when I make the same request from my api using Portals it's not working.
If you invoke the API from the API Portal, the BROWSER follows something called the "same origin policy", which says that requests made from JavaScript running inside the browser can to be sent back only to the origin that served the webpage. If you load your browser page from "myportal.developers.net" then the JS in the browser can make a request back to "myportal.developers,net" but cannot make a request to "www.google.com" or to "myapi-test.apigee.net".
This policy was instituted to prevent cross-site scripting issues. It was viewed as overly restrictive, and so browser makers created a system by which browsers would request access to external sites via something called CORS.
As part of the CORS mechanism, before a browser can send a GET with a header like x-api-key, the browser will send an OPTIONS request. (In case you were not aware, OPTIONS is another HTTP verb, designed for this kind of thing). This is known as the "CORS Pre-flight request".
The web server (in this case, the Apigee-hosted API endpoint) receives the OPTIONS request and needs to respond in a certain way, for the browser to allow the original GET request to go through. If all you see is OPTIONS in the Apigee Trace, then you can conclude that the API Proxy did not respond with the correct CORS response.
Therefore the browser "gives up" and doesn't send the GET.
Why is it working from "Swaggerhub"? Well probably because the request you send from the browser page on swaggerhub.com is being sent back to swaggerhub.com, and then that server is sending it along to your API endpoint. In other words, swagger hub is acting like a relay. The Same-origin policy does not apply to calls made outside a browser, so that calls made from a command line with curl, or calls made from one server to another, will not be restricted.
How can you modify your proxy to handle CORS correctly?
For that, see this old answer from the archives !