CORS issue while sending APIKEY as header.

Not applicable

I am trying to post apikey as header from my angular js to api proxy, but it is giving 401 unauthorized error, i.e when I traced it, it is not receiving header , also receiving as OPTION instead of POST and giving CORS error.Please help.

3 7 2,421
7 REPLIES 7

Not applicable

I have enable CORS for my proxy in APIGEE.

Below are my header setting

<Headers> <Header name="Access-Control-Allow-Origin">request.header.origin</Header> <Header name="Access-Control-Allow-Headers">origin, x-requested-with, accept, apikey</Header> <Header name="Access-Control-Max-Age">3628800</Header> <Header name="Access-Control-Allow-Methods">GET, PUT, POST, DELETE</Header> </Headers>

and this my apikey header configuration:

<APIKey ref="request.header.apikey"/>

Hi Neha

Browsers implicitly send an OPTIONS request as a CORS "preflight" before sending out POST requests (it really should be called "pre-POST"). Your API endpoint (the API proxy in this case) must respond with a CORS preflight response. In the response you specify the origin that should be allowed, the headers that the browser should allow in requests, and the verbs. If the POST request your app is trying to send does not fit within the constraints of the preflight response, then the browser will refuse to send it out. What I mean is this: suppose the preflight response sends back an allow-methods that includes "GET". If your intended request is a POST , then the browser will refuse to send the POST.

In Edge, to handle the preflight, you can code something like this:

  <Flows>
    <Flow name='CORS-Options-PreFlight'>
      <Request/>
      <Response>
        <Step>
          <Name>AM-CORS</Name>
        </Step>
      </Response>
      <Condition>request.verb = 'OPTIONS' and request.header.origin != null</Condition>
    </Flow>


And the AssignMessage policy should look like this:

<AssignMessage name="AM-CORS">
  <Set>
    <Headers>
      <Header name="Access-Control-Allow-Origin">{request.header.origin}</Header>
      <Header name="Access-Control-Allow-Headers">origin, x-requested-with, accept, content-type, user-agent, apikey</Header>
      <Header name="Access-Control-Max-Age">3628800</Header>
      <Header name="Access-Control-Allow-Methods">GET, POST</Header>
    </Headers>
  </Set>
  <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
  <AssignTo createNew="false" transport="http" type="response"/>
</AssignMessage>

You may need to adjust the allow-headers or the allow-methods values.

You gave some code showing headers but you didn't show the entire preflight response. Also you did not show the request that you are sending out from your app. Without those things we cannot fully diagnose your situation.

But, you may be able to figure it out yourself, just with the information I've provided here.

Hint: in the future, you can use the "code" button in the editor bar on this website to format your code. For easier viewing.

@Dino

Thank you for your reply, I tried that but it didn't work for me.

It seems , I am missing something.Can you please have a look once

This is my request code and CORS assign policy code:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ProxyEndpoint name="default">
    <Description/>
    <FaultRules/>
    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Name>verify-api-key</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>
    <PostFlow name="PostFlow">
        <Request/>
        <Response/>
    </PostFlow>
    <Flows>
        <Flow name="PostTest">
            <Description/>
            <Request/>
            <Response/>
            <Condition>(proxy.pathsuffix MatchesPath "/testFlow") and (request.verb = "POST")</Condition>
        </Flow>
        <Flow name="CORS preflight">
            <Description>CORS preflight</Description>
            <Request/>
            <Response>
                <Step>
                    <Name>add-cors</Name>
                </Step>
            </Response>
            <Condition>request.verb = 'OPTIONS' and request.header.origin != null</Condition>
        </Flow>
    </Flows>
    <HTTPProxyConnection>
        <BasePath>/mytesting/v1</BasePath>
        <Properties/>
        <VirtualHost>secure</VirtualHost>
        <VirtualHost>default</VirtualHost>
    </HTTPProxyConnection>
    <RouteRule name="default">
        <TargetEndpoint>default</TargetEndpoint>
    </RouteRule>
</ProxyEndpoint>

TTThis is my CORS policy code
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage async="false" continueOnError="false" enabled="true" name="add-cors">
    <DisplayName>Add CORS</DisplayName>
    <Set>
        <Headers>
            <Header name="Access-Control-Allow-Origin">{request.header.origin}</Header>
            <Header name="Access-Control-Allow-Headers">origin, x-requested-with, accept, content-type, user-agent, apikey</Header>
            <Header name="Access-Control-Max-Age">3628800</Header>
            <Header name="Access-Control-Allow-Methods">GET, POST</Header>
        </Headers>
    </Set>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="response"/>
</AssignMessage>


and here is my header configuration:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<VerifyAPIKey async="false" continueOnError="false" enabled="true" name="verify-api-key">
    <DisplayName>Verify API Key</DisplayName>
    <APIKey ref="request.header.apikey"/>
</VerifyAPIKey>


this is my angular app code snippet to call post operation with header

  var config = {
                headers : {
                   // 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8;',
                    'apikey' : 'abcd'
                }
            }

           $http.post('http://nehadeepak-test.apigee.net/mytesting/v1/testFlow', data, config)
            .success(function (data, status, headers, config) {
                $scope.PostDataResponse = data;
            })

Hi @Neha You also need to configure a NULL target for your pre-flight requests. If the "OPTIONS" request is received, the proxy immediately returns the CORS headers in a response to the client (bypassing the actual default "backend" target).

See this doc page with help on handling pre-flights in Apigee - http://docs.apigee.com/api-services/content/adding-cors-support-api-proxy

Hi,

I added NULL target and I am getting 200 response for OPTIONS but when it calls POST request, it is again giving below CORS error:

"XMLHttpRequest cannot load https://....com.au/myapi/v1/postrequest. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '....(myServer IP)' is therefore not allowed access. The response had HTTP status code 504.

Is it require to add add-cors policy anywhere else apart from OPTION request? I tried to add this for my POST request and for Target Preflow as well but no luck.

Please help.

Please find my code:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ProxyEndpoint name="default">
    <Description/>
    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Name>verify-api-key</Name>
                <Condition>request.verb != "OPTIONS"</Condition>
            </Step>
        </Request>
        <Response/>
    </PreFlow>
    <Flows>
        <Flow name="postreq">
            <Description>postreq</Description>
            <Request/>
            <Response/>
            <Condition>(proxy.pathsuffix MatchesPath "/postrequest") and (request.verb = "POST")</Condition>
        </Flow>
        <Flow name="optionPreFlight">
            <Description>optionPreFlight</Description>
            <Request/>
            <Response>
                <Step>
                    <Name>add-cors</Name>
                </Step>
            </Response>
            <Condition>request.verb == "OPTIONS"</Condition>
        </Flow>
    </Flows>
    <PostFlow name="PostFlow">
        <Request/>
        <Response/>
    </PostFlow>
    <HTTPProxyConnection>
        <BasePath>/myapi/v1</BasePath>
        <VirtualHost>myComp</VirtualHost>
    </HTTPProxyConnection>
    <RouteRule name="NoRoute">
        <Condition>request.verb == "OPTIONS"</Condition>
    </RouteRule>
    <RouteRule name="default">
        <TargetEndpoint>default</TargetEndpoint>
    </RouteRule>
</ProxyEndpoint>

This is my TargetEndpoint Configuration:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<TargetEndpoint name="default">
    <Description/>
    <PreFlow name="PreFlow">
        <Request/>
        <Response/>
    </PreFlow>
    <Flows/>
    <PostFlow name="PostFlow"/>
    <HTTPTargetConnection>
        <URL>http://....dev./myapi/v1</URL>
    </HTTPTargetConnection>
</TargetEndpoint>

This is CORS policy:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage async="false" continueOnError="false" enabled="true" name="add-cors">
    <DisplayName>Add CORS</DisplayName>
    <FaultRules/>
    <Properties/>
    <Add>
        <Headers>
            <Header name="Access-Control-Allow-Origin">{request.header.origin}</Header>
            <Header name="Access-Control-Allow-Headers">origin, x-requested-with, accept, apikey, content-type</Header>
            <Header name="Access-Control-Max-Age">3628800</Header>
            <Header name="Access-Control-Allow-Methods">GET, PUT, POST, DELETE</Header>
        </Headers>
    </Add>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="response"/>
</AssignMessage>

@Neha:

Any solution to this? I am also getting the same issue..

Hi @Neha, @Anshuman Singh

Can you please include 'Access-Control-Allow-Origin' header in your response. Value of this header should be the value that you received in 'origin' header of request.

Also see if you need to remove any unwanted headers while hitting backend.

Please let me know if this works.

Thanks,

Santosh