I'd like to enable CORS on my WSO2 API Manager instance for all endpoints.
I've been through the documentation (which is great) and it suggests altering the repository/conf/api-manager.xml file as there is a CORS configuration node within it (below).
<!--Configuration to enable/disable sending CORS headers in the Gateway response
and define the Access-Control-Allow-Origin header value.-->
<CORSConfiguration>
<!--Configuration to enable/disable sending CORS headers from the Gateway-->
<Enabled>true</Enabled>
<!--The value of the Access-Control-Allow-Origin header. Default values are
API Store addresses, which is needed for swagger to function.-->
<Access-Control-Allow-Origin>*</Access-Control-Allow-Origin>
<!--Configure Access-Control-Allow-Methods-->
<Access-Control-Allow-Methods>GET,PUT,POST,DELETE,PATCH,OPTIONS</Access-Control-Allow-Methods>
<!--Configure Access-Control-Allow-Headers-->
<Access-Control-Allow-Headers>authorization,Access-Control-Allow-Origin,Content-Type</Access-Control-Allow-Headers>
<!--Configure Access-Control-Allow-Credentials-->
<!-- Specifying this header to true means that the server allows cookies (or other user credentials) to be included on cross-origin requests.
It is false by default and if you set it to true then make sure that the Access-Control-Allow-Origin header does not contain the wildcard (*)
-->
<Access-Control-Allow-Credentials>true</Access-Control-Allow-Credentials>
</CORSConfiguration>
This file doesn't seem to apply this CORS configuration to all endpoints though. I receive the correct Access Control headers when making requests to API endpoints that I've published but I don't receive them when I hit the token endpoints (default - '/token', '/revoke').
How am I able to achieve this?
CORS configurations are valid for the APIs created using the Publisher applications. The token apis (- '/token', '/revoke') are not covered from this configurations.
CORS headers are handled using a handler
org.wso2.carbon.apimgt.gateway.handlers.security.CORSRequestHandler
If you open a synapse configuration for an api in /repository/deployment/server/synapse-configs/default/api you would find this handler.
You can set this handler to the RevokeAPI.xml and TokenAPI.xml as well. (these are in the same location /repository/deployment/server/synapse-configs/default/api). It would be something like this in the configuration file
<handlers>
<handler class="org.wso2.carbon.apimgt.gateway.handlers.security.CORSRequestHandler">
<property name="apiImplementationType" value="ENDPOINT"/>
</handler>
<handler class="org.wso2.carbon.apimgt.gateway.handlers.ext.APIManagerCacheExtensionHandler"/>
<handler class="org.wso2.carbon.apimgt.gateway.handlers.common.SynapsePropertiesHandler"/>
</handlers>
The CORS configuration in the api-manager.xml will be only applied for the APIs created through the API Manager. It will not apply those configurations to Token APIs such as /token and /revoke.
The token API related configurations are located in {PRODUCT_HOME}/repository/deployment/server/synapse-configs/default/api directory.
You can edit the _TokenAPI_.xml and add CORS headers if you needed. You may refer[1] as useful resource.
[1] - http://blog.lakmali.com/2013/10/how-to-add-additional-headers-to-wso2.html
Related
I am using WSO2 API Manager (version 3.0.1) as front-end for accessing data via an API call to CKAN (version 2.8.2).
A private CKAN data set requires an authorization token as described here.
"When calling an API function that requires authorization, you must authenticate yourself by providing your API key with your HTTP request."
How is this accomplished in WSO2? Specifically, what configuration files/settings need to change to make this happen?
I see from this documentation that if configured in Eclipse using a tooling plug-in it can be accomplished with something like this (Step 23):
curl -k -H "Authorization: Bearer api-key-for-WSO2-goes-here" -H "Custom: Bearer api-key-for-CKAN-goes-here" https://my-wso2-host-goes-here:8243/test/1.0.0
However, these instructions require using Eclipse. But how can this be accomplished without Eclipse? I.e. what configuration files/settings need to be modified on the server or in the WSO2 API Publisher and/or the WSO2 API Dev Portal to pass the authorization token for CKAN through WSO2 API-M?
You do not have to use Eclipse for this. In the tutorial Eclispse plugin is used as a tool to generate the sequence easily. In that tutorial we needed a sequence
in the first place because the authorization header required by the backend is "Authorization". In WSO2 APIM this is a reserved header to pass the internally generated token. Therefore we first pass the backend token in a custom header with a different header name and then copy this value to Authorization header in the in-sequence.
The sequence would look like below.
<sequence xmlns="http://ws.apache.org/ns/synapse" name="authorization_header_exchange">
<property name="X-Authorization" expression="get-property('transport', 'X-Authorization')" scope="default" type="STRING"/>
<property name="Authorization" expression="get-property('X-Authorization')" scope="transport" type="STRING" description=""/>
<property name="X-Authorization" scope="transport" action="remove"/>
Refer [1] for more info.
However in your case you can send the api key in X-CKAN-API-Key along with the request itself without using a mediation sequence.
[1]. https://docs.wso2.com/display/APICloud/Sample+Mediation+Sequences#SampleMediationSequences-Passinganauthorizationheadertoyourbackend
I'm answering my own question...
TLDR
The answer by #naoko above is correct: to pass CKAN authorization through WSO2 API-M include X-CKAN-API-Key as a header with a value set to your CKAN user's private CKAN API key.
Long Version
Pass the CKAN API key like this:
curl -k -H "Authorization: Bearer wso2-app-key-here" -H "X-CKAN-API-Key: ckan-authorization-key-here" https://myWso2DeveloperPortal.com:8243/daas/3.0.1/action/resource_show?id=resource-id-of-CKAN-dataset-here
(Use -k if the host has a self-signed https certificate)
Where...
wso2-app-key-here is the application key found in the WSO2 Developer Portal.
ckan-authorization-key-here is your user account's private key in CKAN. (It can be found on your user profile page in the CKAN UI.)
resource-id-of-CKAN-dataset-here is the resource id of the dataset you want to query.
The resource_show method in this example will return metadata for the given CKAN resource. Other CKAN methods are invoked in a similar manner.
This is all thanks to CKAN for having an alternative to passing the key in a header named Authorize. In the case of CKAN, the variable X-CKAN-API-Key can be used. And this can be easily passed as shown above.
Mea culpa for not catching that in the CKAN docs in the first place (It's right there in my very own screenshot above!)...had I read thoroughly it would have saved a SO post for better or worse;)
Had CKAN not provided the alternative with X-CKAN-API-Key then this can be accomplished in version 3.0.0 as described in these pages:
"Passing a Custom Authorization Token to the Backend"
https://apim.docs.wso2.com/en/latest/Learn/APIGateway/MessageMediation/passing-a-custom-authorization-token-to-the-backend/
FWIW, I actually tried that before trying the X-CKAN-API-Key solution and it didn't work. Maybe I was doing something wrong. But since the X-CKAN-API-Key solution works for me I'm calling it done.
I am trying to subscribe a published API in WSO2am-1.7.0 but it gives no response. I have published a restful client of type GET. I am testing this in the API console of the WSO2AM by passing the values.The result should show me a JSON output which I get when hitting the restful client url in the browser.Even I tried out the example 'Find Tweets', that does not work too.
User has to enable CORS configuration in the api-manager.xml to try the swagger client. Check here for more
Eg:
<CORSConfiguration>
<!-Configuration to enable/disable sending CORS headers from the Gateway->
<Enabled>true</Enabled>
<!--The value of the Access-Control-Allow-Origin header. Default values are
API Store addresses, which is needed for swagger to function.-->
<Access-Control-Allow-Origin>http://10.100.1.35:9763, https://10.100.1.35:9443</Access-Control-Allow-Origin>
<!-Configure Access-Control-Allow-Headers->
<Access-Control-Allow-Headers>authorization,Access-Control-Allow-Origin,Content-Type</Access-Control-Allow-Headers>
</CORSConfiguration>
We have our API being managed by WS02 API manager, but there seems to be some issue with the way it constructs the outgoing request into the configured endpoint URL. We see this sort of error from our endpoint when we make a request to the API manager:
Cannot bind to address "http://<HOST>:<PORT>http://<HOST>:<PORT>/<RESOURCE>
The URL is clearly incorrect as it is prepending the host part of the URL twice. We've put a debugging proxy in between the API manager and our endpoint and it shows the outgoing request looks like this:
GET http://<HOST>:<PORT>/<RESOURCE> HTTP/1.1
...
Host: <HOST>:<PORT>
It isn't normal for the host to be included in the first line; that should come from the "Host" header. But as it is, it makes sense we are getting the above error. Note, when we proxy this through something like Nginx, it works fine, but the server we are actually using for our endpoint doesn't like it. I'm guessing Nginx has been written in such a way so that it can resolve this kind of (technically incorrect) request.
We are adding propery 'POST_TO_URI' to our synapse API configuration in order to make the outgoing URL a complete URL [1]. This is useful when sending the messages through a proxy server. You can remove that property by modifying your API in AM_HOME/repository/deployment/server/synapse-configs/default/api/ directory. Remove the below property in your relevant APIs which sending requests to such backend servers.
<property name="POST_TO_URI" value="true" scope="axis2"/>
[1]https://docs.wso2.org/display/ESB460/HTTP+Transport+Properties
We have just installed our WSO2 ESB, and we are trying to create some proxies services with customs endpoints.
The default endoint format is:
http://{host}:{port}/services/{Proxy Service Name}
I'd like to have something like:
http://{host}:{port}/services/utilities/{Proxy Service Name}
http://{host}:{port}/services/public/{Proxy Service Name}
I followed this tutorial:
http://wso2.org/library/knowledge-base/2011/01/custom-urls-wso2-esb-proxy-services
but we have a problem, when I send a request to my custom endpoint, I have no answer.
suggestions?
I assume that you were able to properly create a custom endpoint and "I have no answer" means you didn't get any response. If it is the case following are the possible reasons for that,
Proxy service endpoint didn't receive the request
Proxy service didn't configured properly to response back
So test whether the 1 is the reason you can simply put a log mediator with following configuration in inSequence,
<log level="full"/>
then if the proxy service received a message it will log it in console. If that works could you please post your proxy service configuration to check whether it is properly defined.
Well, it seems that we've found a solution, I'm going to resume the full solution.
As the tutorial indicates, to costumize your proxy service endpoint, you have to add the following handler on the axis2.xml configuration:
<handler name="CustomURIBasedDispatcher" class="org.apache.synapse.core.axis2.CustomURIBasedDispatcher"/>
Then, you can customize your endpoint on the design view or on the source view, I've choosen the source view, adding this parameter:
<parameter name="ServiceURI">/services/intern</parameter>
The custom endpoint is autogenerated as:
http://{host}:{port}/services/intern.myWebservice
But I has not worked for me. If I send a request to the custom endpoint, I have no response.
I've solved the problem, adding to the "ServiceURI" parameter the name of the service:
<parameter name="ServiceURI">/services/intern/myWebService</parameter>
then you have to send the request to the following endpoint:
http://{host}:{port}/services/intern/myWebService
So now you have a custom endpoint for every proxy service.
Thanks Malith for your help.
I have a webservice and a Silverlight application.
I also have a crossdomain.xml and clientaccesspolicy.xml
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="*">
<domain uri="*"/>
</allow-from>
<grant-to>
<resource path="/" include-subpaths="true"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
here my cross domain policy
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy
SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="http://localhost/MHVWS/MachineHistoryWS.asmx" />
</cross-domain-policy>
My web service is being hosted in IIS.
With this configuration I still have this kind of error:
An error occurred while trying to make a request to URI 'http://localhost/MHVWS/MachineHistoryWS.asmx'. This could be due to attempting to access a service in a cross-domain way without a proper cross-domain policy in place, or a policy that is unsuitable for SOAP services. You may need to contact the owner of the service to publish a cross-domain policy file and to ensure it allows SOAP-related HTTP headers to be sent. This error may also be caused by using internal types in the web service proxy without using the InternalsVisibleToAttribute attribute. Please see the inner exception for more details.
Please help
You only need one policy file. You dont require both.
Be sure one (or both) of those policy files exist in the same location (domain) as the webservice.
To debug and see what is going on, use a tool like Fiddler to verify the url path of the policy xml file the client is looking for.