Cross domain problems with WSO2 API Manager - cross-domain

We have develop some APIs for a client and we have published them through API Manager. We have provided the client with some code examples on PHP which work fine. The only problem is that they are using those APIs through AJAX in a different domain to the one associated with AM. Is this a cross domain problem?
I have tried setting the apache server in front of API Manager with the following headers, so that cross domain is allowed
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Authorization, Content-Type, Accept
Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS
Access-Control-Allow-Origin: *
But even with these headers, I still get a 401 Unauthorizaed when making calls to AM. I have tried making the requests directly to AM without going through Apache (port 8282) but we still get the same problem.

Yes this is a cross domain problem. I would suggest you to try out below.
Is your API allowed for 'OPTIONS' verb in None Auth Type? [1]To verify that send a curl request to API with out OAuth headers. If you are getting a 200 OK response with CORS headers which you have mentioned then that should be fine.
ex:
curl -v -X OPTIONS http://localhost:8280/testapi
If it is not returning a success message, then your backend might be not supporting OPTIONS method. You can verify that by directly sending an OPTIONS request to your backend service. Either you can enable OPTIONS in your backend service or avoid the OPTIONS call reaching the backend by modifying the API synapse configuration.
ex:-
<api name="admin--TestAPI" context="/test" version="1.0" version-type="url">
<resource methods="POST GET OPTIONS DELETE PUT" url-mapping="/*">
<inSequence>
<filter source="get-property('axis2', 'HTTP_METHOD')" regex="OPTIONS">
<then>
<log level="custom">
<property name="Message" value="Received OPTIONS call, sending back headers"/>
</log>
<property name="Access-Control-Request-Headers" value="authorization,content-type" scope="transport"/>
<property name="Access-Control-Allow-Headers" value="authorization,Access-Control-Allow-Origin,Content-Type" scope="transport"/>
<property name="Access-Control-Allow-Methods" value="GET,POST,PUT,DELETE,OPTIONS" scope="transport"/>
<property name="Access-Control-Allow-Origin" value="*" scope="transport"/>
<property name="RESPONSE" value="true" scope="default" type="STRING"/>
<header name="To" action="remove"/>
<send/>
</then>
<else>
<property name="POST_TO_URI" value="true" scope="axis2"/>
<filter source="$ctx:AM_KEY_TYPE" regex="PRODUCTION">
<then>
<send>
<endpoint name="admin--StudentAPI_APIEndpoint_0">
<address uri="http://localhost:8080/sample/1.0/one/">
<timeout>
<duration>30000</duration>
<responseAction>fault</responseAction>
</timeout>
<suspendOnFailure>
<errorCodes>-1</errorCodes>
<initialDuration>0</initialDuration>
<progressionFactor>1.0</progressionFactor>
<maximumDuration>0</maximumDuration>
</suspendOnFailure>
<markForSuspension>
<errorCodes>-1</errorCodes>
</markForSuspension>
</address>
</endpoint>
</send>
</then>
<else>
<sequence key="_sandbox_key_error_"/>
</else>
</filter>
</else>
</filter>
</inSequence>
<outSequence>
<send/>
</outSequence>
</resource>
<handlers>
<handler class="org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler"/>
<handler class="org.wso2.carbon.apimgt.gateway.handlers.throttling.APIThrottleHandler">
<property name="id" value="A"/>
<property name="policyKey" value="gov:/apimgt/applicationdata/tiers.xml"/>
</handler>
<handler class="org.wso2.carbon.apimgt.usage.publisher.APIMgtUsageHandler"/>
<handler class="org.wso2.carbon.apimgt.usage.publisher.APIMgtGoogleAnalyticsTrackingHandler"/>
<handler class="org.wso2.carbon.apimgt.gateway.handlers.ext.APIManagerExtensionHandler"/>
</handlers>
</api>
Then add Access-Control-Allow-Origin as well to the list of Access-Control-Allow-Headers and keep the other headers as it is.
ex: Access-Control-Allow-Headers: authorization,Access-Control-Allow-Origin,Content-Type
If you are still getting the error, can you provide the detailed error message or the sample PHP client code?
[1]http://docs.wso2.org/display/AM160/Adding+Documentation+Using+Swagger

Please change Access-Control-Allow-Headers value to authorization,Access-Control-Allow-Origin,Content-Type and check.

Related

Only POST requests with iisnode unauthorized

I have an Express API running on IIS with iisnode. I have only Windows Authentication enabled and can send GET requests.
POST requests however return "401 Unauthorized: Access is denied due to invalid credentials."
I include credentials in the React fetch request:
await fetch("https://website", {
method: "POST",
credentials: "include",
headers: etc..)
and in my Express code:
app.use(cors({ origin: "https://website", credentials: true }))
I have the CORS module installed and in my web.config I have:
<cors enabled="true">
<add origin="https://website" allowCredentials="true">
<allowHeaders allowAllRequestedHeaders="true" />
</add>
</cors>
I also have in my web.config:
<system.web>
<authentication mode="Windows"/>
<authorization>
<add accessType="Allow" verbs="GET, OPTIONS, POST, PUT" users="*"/>
<allow roles="*" users="*" />
<deny users=?" />
</authorization>
</system.web>
I have tried removing "WebDAV" but that did not work. I also have set "ExtensionlessUrlHandler-Integrated-4.0" to allow all verbs. My web.config contains all the necessary code to make iisnode work, which I have not included in the post. I also tried adding a "allowMethods" tag inside the CORS tag but that did not work.
Any ideas on why my GET and OPTIONS requests validate correctly, but my POST requests get blocked? A solution should not include enabling "Anonymous authentication" because that is not an option.
I resolved the issue by removing the <add accessType="Allow" verbs="GET, OPTIONS, POST, PUT" users="*" /> line from within authorization.

WSO2 rabbitMQ - channels created and not closed - memory leak problem

I am using WSO2 ESB with RabbitMQ, I have one proxy service and one sequence.
The proxy service works as consumer for RabbitMQ queue (via rabbitmq transport), consumed messages are send to HTTP endpoint.
The sequence works as producer to add actions in queue, calling an endpoint.
I also have an API that, for each call, inserts in the queue. Everything works correctly, but every time that we call the API, in the rabbit queue many channels are created without closing them, causing the "memory leak" problem on the Rabbit server machine.
We tried to create "direct" and "fanout" exchange, but did not resolve the memory leak problem.
Below the sequence code:
<sequence name="add-insertqueue-tostore" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<property name="FORCE_SC_ACCEPTED" scope="axis2" type="STRING" value="true"/>
<property name="OUT_ONLY" scope="default" type="STRING" value="true"/>
<call>
<endpoint key="gov:endpoints/rabbit/insert-toqueue.xml"/>
</call>
<log level="full">
<property name="Sequence" value="AddToQueue"/>
<property name="step" value="Message inserted"/>
</log>
<property name="FORCE_SC_ACCEPTED" scope="axis2" type="STRING" value="false"/>
<property name="OUT_ONLY" scope="default" type="STRING" value="false"/>
</sequence>
below the endpoint code
<endpoint name="insert-toqueue" xmlns="http://ws.apache.org/ns/synapse">
<address uri="rabbitmq:/AMQPProxy?rabbitmq.server.host.name=rabbit.server&rabbitmq.server.port=5672&rabbitmq.server.user.name=username&rabbitmq.server.password=password&rabbitmq.queue.name=queue&rabbitmq.server.virtual.host=/virtual-host&rabbitmq.exchange.name=exchange"/>
</endpoint>
below the consumer code
<proxy name="rabbit-consumer" startOnLoad="true" trace="enable" transports="rabbitmq" xmlns="http://ws.apache.org/ns/synapse">
<target>
<inSequence>
<property action="remove" name="SOAPAction" scope="transport"/>
<property action="remove" name="WSAction" scope="transport"/>
<property name="ContentType" scope="transport" type="STRING" value="application/json"/>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<property name="HTTP_METHOD" scope="axis2" type="STRING" value="POST"/>
<property expression="json-eval($.name)" name="name" scope="default" type="STRING"/>
<property expression="json-eval($.surname)" name="surname" scope="default" type="STRING"/>
<log level="full"/>
<call-template target="my-template">
<with-param name="name" value="{get-property('name')}" xmlns:ns="http://org.apache.synapse/xsd"/>
<with-param name="surname" value="{get-property('surname')}" xmlns:ns="http://org.apache.synapse/xsd"/>
</call-template>
<property name="OUT_ONLY" scope="default" type="STRING" value="true"/>
</inSequence>
<outSequence/>
<faultSequence/>
</target>
<parameter name="rabbitmq.exchange.type">fanout</parameter>
<parameter name="rabbitmq.exchange.name">exchange</parameter>
<parameter name="rabbitmq.queue.name">queue</parameter>
<parameter name="rabbitmq.connection.factory">AMQPConnectionFactory</parameter>
</proxy>
Do you know how to resolve this problem? thanks a lot
Did you try to reboot?
Normally it works.
Bye
When configure RabbitMQ sender maybe u can try "cached" one.
<transportSender name="rabbitmq" class="org.apache.axis2.transport.rabbitmq.RabbitMQSender">
<parameter name="CachedRabbitMQConnectionFactory" locked="false">
<parameter name="rabbitmq.server.host.name" locked="false">localhost</parameter>
<parameter name="rabbitmq.server.port" locked="false">5672</parameter>
<parameter name="rabbitmq.server.user.name" locked="false">user</parameter>
<parameter name="rabbitmq.server.password" locked="false">abc123</parameter>
</parameter>
</transportSender>
Doc link : https://docs.wso2.com/display/EI611/RabbitMQ+AMQP+Transport

Setting up CORS in web.config (IIS) for non .NET app

I'm trying to allow CORS over a site, using the IIS CORS module (https://www.iis.net/downloads/microsoft/iis-cors-module), but I'm having troubles.
This is my web.config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<cors enabled="true" failUnlistedOrigins="true">
<add origin="https://my.site" allowCredentials="false" maxAge="120">
<allowHeaders allowAllRequestedHeaders="true"></allowHeaders>
<allowMethods>
<add method="GET" />
<add method="POST" />
<add method="PUT" />
</allowMethods>
</add>
</cors>
</system.webServer>
</configuration>
with this setup, the OPTIONS (pre-flight) request works fine, but any further request (GET, POST) raise a browser exception because of missing Access-Control-Allow-Origin
I tryed to add the following to web.config:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="https:/my.site" />
</customHeaders>
</httpProtocol>
but in this way the OPTIONS fails because there're 2 instances of Access-Control-Allow-Origin
Using only custom header the pre-flight fails with code 500 (I think IIS doesn't support OPTIONS method without the CORS module).
IIS CORS module documentation is very poor and googling I only find info related to .NET code, but it's not my case. I can't modify code (and it's not .NET), I need to act on IIS.
How can I make IIS respond properly to CORS requests ?
From the code you have posted, it looks like you have not added your origin correctly.
The origin line should contain a (Fully Qualified Domain Name) FQDN or some regex that matches it.
A correct line would look like:
<add origin="https://my.site.com" allowCredentials="false" maxAge="120">
You can allow subdomains of your domain using:
<add origin="https://*.site.com" allowCredentials="false" maxAge="120">
From the sounds of it, you aren't receiving the headers you want back from the web server. This may be due to the webserver Only returning CORS safe headers.
Using the IIS CORS Blog from Microsoft, I've added in config that will expose the headers back in the request.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<cors enabled="true" failUnlistedOrigins="true">
<add origin="https://my.site" allowCredentials="false" maxAge="120">
<allowHeaders allowAllRequestedHeaders="true">
<add header="DNT" />
<add header="Host" />
<add header="Origin" />
<add header="Referrer" />
<add header="User-Agent" />
</allowHeaders>
<allowMethods>
<add method="GET" />
<add method="POST" />
<add method="PUT" />
</allowMethods>
<exposeHeaders>
<add header="DNT" />
<add header="Host" />
<add header="Origin" />
<add header="Referrer" />
<add header="User-Agent" />
</exposeHeaders>
</add>
</cors>
</system.webServer>
</configuration>
However, according to This CORS documentation OPTIONS requests don't get the Allow Headers or Expose Headers configuration applied to them. Hopefully that's not the issue here though.
Below I've added the most basic CORS request I can think of. If this request works, then it may be a client side problem you are encountering.
fetch('example.com', {
method: 'GET',
mode: 'cors',
credentials: 'include',
headers: { 'Authorization': authString }
}).then(
response => response.json()
); // parses JSON response into native JavaScript objects

How to connect by MDS excel add-in using HTTPS?

I've switched MDS access from HTTP into HTTPS.
Web interface works ok
Excel add-in generates an error during a connection attempt
The HTTP request was forbidden with client authentication scheme 'Negotiate'.
The remote server returned an error: (403)Forbidden. (System)
What should be done to work with excel using HTTPS?
The Web Application will continue to work after switching to SSL but the Excel add in will not. To resolve this you must edit the web.config of the Master Data Services web application. See below link for full details, I believe you would start at step 10 given context.
https://learn.microsoft.com/en-us/sql/master-data-services/install-windows/secure-a-master-data-manager-web-application?view=sql-server-ver15
In my experience the portion needed to make SSL work is already in the web.config but commented out, you just need to uncomment it out and comment out the section that is for Non SSL. Note there are two different sections.
This is what my bindings section in the web.config looks like after configuring for SSL.
<bindings>
<wsHttpBinding>
<binding name="mdsWsHttpBinding" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxDepth="2147483647" maxNameTableCharCount="2147483647" maxStringContentLength="2147483647" />
<!--Non-SSL implementations.-->
<!-- <security mode="Message"> -->
<!-- <message clientCredentialType="Windows" /> -->
<!-- </security> -->
<!--SSL implementations-->
<security mode="Transport">
<message clientCredentialType="Windows" />
</security>
</binding>
</wsHttpBinding>
<basicHttpBinding>
<binding name="mdsBasicHttpBinding" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxDepth="2147483647" maxNameTableCharCount="2147483647" maxStringContentLength="2147483647" />
<!-- Non-SSL implementations.-->
<!-- <security mode="TransportCredentialOnly"> -->
<!-- <transport clientCredentialType="Windows" /> -->
<!-- </security> -->
<!-- SSL implementations -->
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>

Remove cache HTTP response headers from Web Api in Azure

I am trying to remove unwanted Cache-Control, Pragma and Expires HTTP headers in responses from a Web Api 2 project hosted on an Azure website in Standard mode.
I have tried the following in Global.asax Application_PreSendRequestHeaders:
var headers = ((HttpApplication)sender).Context.Response.Headers;
headers.Remove("Cache-Control");
headers.Remove("Pragma");
headers.Remove("Expires");
This works when debugging in Visual Studio. But on Azure, the headers are only removed for GET requests and not HEAD or POST requests.
Grateful for any suggestions!
Azure Web Sites supports the request filtering module, so you can do this in your web.config:
<system.webServer>
<httpProtocol>
<customHeaders>
<remove name="Cache-Control" />
<remove name="Pragma" />
<remove name="Expires" />
</customHeaders>
</httpProtocol>
</system.webServer>
Disclaimer: I am not condoning the removal of these headers, which are an essential part of the HTTP protocol.
Removing cache headers says to clients "it is entirely up to you to decide how to cache this response", which may result in odd and hard-to-reproduce errors in production. If you want to disable caching, you should set these headers to values which explicitly disable caching:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Cache-Control" value="no-cache" />
<add name="Pragma" value="no-cache" />
<add name="Expires" value="-1" />
</customHeaders>
</httpProtocol>
</system.webServer>

Resources