Hi Team,
I am implementing CORS policy . I have added in CORS policy in pre flow and target pre flow and Options Preflight flow .
The issue I am getting whenever Default Fault Rule is called it is not adding CORS headers in response
CORS policy
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<CORS continueOnError="false" enabled="true" name="CORS">
<DisplayName>CORS</DisplayName>
<AllowOrigins>{request.header.origin}</AllowOrigins>
<AllowMethods>GET, PUT, POST, DELETE</AllowMethods>
<AllowHeaders>authorization, origin, x-requested-with, accept, content-type, referer</AllowHeaders>
<ExposeHeaders>*</ExposeHeaders>
<MaxAge>3628800</MaxAge>
<AllowCredentials>false</AllowCredentials>
<GeneratePreflightResponse>true</GeneratePreflightResponse>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</CORS>
RF-CommonError
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<RaiseFault async="false" continueOnError="false" enabled="true" name="RF-CommonError">
<FaultResponse>
<Set>
<Payload contentType="application/json">
{
"errorCode": "{flow.error.code}",
"errorType": "{flow.error.type}",
"errorMessage": "{flow.error.message}"
}
</Payload>
<StatusCode>{flow.error.status}</StatusCode>
<ReasonPhrase>{flow.error.reason}</ReasonPhrase>
</Set>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<!--<Copy source="request">-->
<!-- <Headers/>-->
<!--</Copy>-->
</FaultResponse>
</RaiseFault>
<DefaultFaultRule name="fault-rule">
<AlwaysEnforce>true</AlwaysEnforce>
<Step>
<Name>CORS</Name>
</Step>
<Step>
<Name>AM-500InternalServerError</Name>
</Step>
<Step> 500InternalServerError
<Name>RF-CommonError</Name>
<Condition>(fault.name != "RaiseFault")</Condition>
</Step>
</DefaultFaultRule>
AM-500InternalServerError this policy is to set default error message
can any one guide me on this issue
Solved! Go to Solution.
Yes, two things
It could be that using a RaiseFault in a FaultRule is causing the problem, which requires you to set a header in AssignMessage.
@Sau101 wrote:
I have added in CORS policy in pre flow and target pre flow and Options Preflight flow .
You need to attach the CORS policy once. In the Proxy Request preflow. Just one attachment.
Done Same thing but its giving error
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
when the default fault rule is called .
Here I am setting up error messages based on conditions and its giving response in default fault rule
like oauthV2.OAuthV2-VerifyAccessToken.failed == true
I have added step for raise fault for custom error message format like
{
"errorCode": "{flow.error.code}",
"errorType": "{flow.error.type}",
"errorMessage": "{flow.error.message}"
} getting these variable from fault rule assign message
<FaultRules>
<FaultRule name="Unauthorized">
<Condition>(oauthV2.OAuthV2-VerifyAccessToken.failed == true)</Condition>
<Step>
<Name>AM-401Unauthorized</Name>
</Step>
</FaultRule>
<FaultRule name="Product not added to app">
<Condition>oauthV2.VA-APIKeyVerifier.fault.name == "oauth.v2.InvalidApiKeyForGivenResource"</Condition>
<Step>
<Name>AM-500InternalServerError</Name>
</Step>
</FaultRule>
<FaultRule name="Quota Limit Exceeded">
<Condition>(fault.name = "QuotaViolation")</Condition>
<Step>
<Name>AM-429QuotaError</Name>
</Step>
</FaultRule>
<FaultRule name="SC-Error">
<Condition>(fault.name Matches "ExecutionFailed") </Condition>
<Step>
<Name>AM-InvalidSSO</Name>
<Condition>(CyberArkOAuthResponse.status.code != "200") </Condition>
</Step>
</FaultRule>
</FaultRules>
<DefaultFaultRule name="fault-rule">
<Step>
<Name>AM-500InternalServerError</Name>
</Step>
<Step>
<Name>RF-CommonError</Name>
<Condition>(fault.name != "RaiseFault")</Condition>
</Step>
<AlwaysEnforce>true</AlwaysEnforce>
</DefaultFaultRule>
My suggestion: simplify your scenario to see what is really going on.
I just tried this in my Apigee X organization, and it works as expected.
I have a simple proxy with a CORS policy in the Preflow. And a conditional flow that calls VerifyAPIKey. That one does not always execute. The VerifyAPIKey is there, so that I can conditionally cause a fault.
The proxy has a DefaultFaultRule which injects a header into the response. The DFR will execute in the fault condition that occurs if the proxy executes the conditional flow that calls VerifyAPIKey, but there is no api key. I see the expected behavior from this proxy:
This occurs whether there is a fault or not. In other words, Apigee is behaving as expected. (See the terminal session below) So there is something else going on wrong with yours.
Looking at your CORS policy, it may be that your Max-Age is set to 3628800, which equates to 42 days. Is it possible that your browser has cached an older version of the CORS response, and is relying on that older cache, and is never connecting with Apigee at all? If you would like to eliminate this as a possibility, use the browser developer tools and turn off the in-browser caching. (Google it if you don't know which button to click)
Otherwise I don't know what to suggest. I've attached my proxy so you can try it in your environment.
My session:
$ curl -i $apigee/cors-loopback/t2 -H "Origin:http://localhost"
HTTP/2 200
apiproxy: cors-loopback r4
content-type: application/json
access-control-allow-origin: http://localhost
access-control-expose-headers: *
access-control-allow-credentials: true
x-request-id: 02b7fdd2-ea30-47fb-8421-a85411fd5a97
content-length: 24
date: Wed, 24 Apr 2024 19:47:40 GMT
via: 1.1 google, 1.1 google
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
{
"status" : "ok"
}
$ curl -i $apigee/cors-loopback/t1 -H "Origin:http://localhost"
HTTP/2 401
content-type: application/json
apiproxy: cors-loopback r4
access-control-allow-origin: http://localhost
access-control-expose-headers: *
access-control-allow-credentials: true
x-request-id: 7fadc9f9-c89f-444f-8c02-409f04b859d4
content-length: 150
date: Wed, 24 Apr 2024 19:47:45 GMT
via: 1.1 google
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
{"fault":{"faultstring":"Failed to resolve API Key variable request.queryparam.apikey","detail":{"errorcode":"steps.oauth.v2.FailedToResolveAPIKey"}}}
$ curl -i $apigee/cors-loopback/t1
HTTP/2 401
content-type: application/json
apiproxy: cors-loopback r4
x-request-id: f6a6351b-8665-4496-90fd-47e6f0318ac9
content-length: 150
date: Wed, 24 Apr 2024 19:47:55 GMT
via: 1.1 google
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
{"fault":{"faultstring":"Failed to resolve API Key variable request.queryparam.apikey","detail":{"errorcode":"steps.oauth.v2.FailedToResolveAPIKey"}}}
Hi
Thanks for the guidance.
The issue was in default fault rule raise fault policy.
It was not passing the Access-Control-Allow-Origin in response header even if the origin was present in the request .
For the solution I have updated the RF-CommonError
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<RaiseFault async="false" continueOnError="false" enabled="true" name="RF-CommonError">
<FaultResponse>
<Set>
<Payload contentType="application/json">
{
"errorCode": "{flow.error.code}",
"errorType": "{flow.error.type}",
"errorMessage": "{flow.error.message}"
}
</Payload>
<StatusCode>{flow.error.status}</StatusCode>
<ReasonPhrase>{flow.error.reason}</ReasonPhrase>
<Headers>
<Header name="Access-Control-Allow-Origin">{firstnonnull(request.header.origin,*)}</Header>
</Headers>
</Set>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</FaultResponse>
</RaiseFault>
by This solution its working now.
Guide me if required any changes
Yes, two things
It could be that using a RaiseFault in a FaultRule is causing the problem, which requires you to set a header in AssignMessage.
Thanks for the help ,
It worked with adding Assign Message instead of Raise Fault .
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage continueOnError="false" enabled="true" name="AM-CommonError">
<DisplayName>AM-CommonError</DisplayName>
<Properties/>
<Set>
<Payload contentType="application/json">
{
"errorCode": "{flow.error.code}",
"errorType": "{flow.error.type}",
"errorMessage": "{flow.error.message}"
}
</Payload>
<StatusCode>{flow.error.status}</StatusCode>
<ReasonPhrase>{flow.error.reason}</ReasonPhrase>
</Set>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<AssignTo createNew="false" transport="http" type="request"/>
</AssignMessage>
User | Count |
---|---|
1 | |
1 | |
1 | |
1 | |
1 |