I am facing Cross origin issue when tried to call a ESB Rest API which has Entitlement policy. Please find the below client call, ESB API, and Handler.
- Ajax call:
$.ajax({
beforeSend: function(xhr) {
xhr.setRequestHeader('Authorization', 'Bearer 5d8ce0224d82cca7fb55fdcf4015b67');
},
withCredentials: true,
dataType: "json",
type: 'GET',
url: relativeURL+"/test,
},
success: function(json)
{}});
- ESB API Configuration
<api xmlns="http://ws.apache.org/ns/synapse" name="CustomerApi" context="/CustomerApi">
<resource methods="POST GET OPTIONS DELETE PUT">
<inSequence>
<log level="custom">
<property name="Message Flow" value="Customer Search API - IN"> </property>
<property name="HTTP_METHOD IS###########" expression="$axis2:HTTP_METHOD"></property>
<property name="ip address" expression="get-property('axis2','REMOTE_ADDR')"></property>
</log>
<property name="Authorization" expression="get-property('transport','Authorization')"></property>
<property name="Access-Control-Allow-Credentials" value="true" scope="transport"></property>
<property name="Access-Control-Allow-Headers" value="authorization,Access-Control-Allow-Origin,Content-Type,origin,accept,X-Requested-With" scope="transport"></property>
<property name="Access-Control-Allow-Methods" value="GET,POST,PUT,DELETE,OPTIONS" scope="transport"></property>
<property name="Access-Control-Allow-Origin" value="*" scope="transport"></property>
<property name="xacml_use_rest" value="true" scope="axis2" type="STRING"></property>
<property name="xacml_resource_prefix" value="/api/customers" scope="axis2"></property>
<property name="xacml_resource_prefix_only" value="true" scope="axis2"></property>
<property name="TIME_IN" expression="get-property('SYSTEM_TIME')" scope="default" type="LONG"></property>
<log level="custom">
<property name="Authorization.........." expression="get-property('transport','Authorization')"></property>
</log>
<entitlementService remoteServiceUrl="https://localhost:9444/services" remoteServiceUserName="admin" remoteServicePassword="enc:kuv2MubUUveMyv6GeHrXr9il59ajJIqUI4eoYHcgGKf/BBFOWn96NTjJQI+wYbWjKW6r79S7L7ZzgYeWx7DlGbff5X3pBN2Gh9yV0BHP1E93QtFqR7uTWi141Tr7V7ZwScwNqJbiNoV+vyLbsqKJE7T3nP8Ih9Y6omygbcLcHzg=" callbackClass="org.wso2.carbon.identity.entitlement.mediator.callback.UTEntitlementCallbackHandler" client="basicAuth">
<onReject>
<log level="custom">
<property name="Message Flow" value="REJECTED@ Dobbies"></property>
</log>
<property name="HTTP_SC" value="401" scope="axis2" type="STRING"></property>
<payloadFactory media-type="xml">
<format>
<oatherizationresponse xmlns="">Not Authorized </oatherizationresponse>
</format>
<args></args>
</payloadFactory>
<respond></respond>
</onReject>
<onAccept>
<log level="custom">
<property name="Message Flow" value="ACCEPTED@ Dobbies"></property>
</log>
<property name="Authorization" expression="fn:concat('Basic ', base64Encode('test:test'))" scope="transport"></property>
<send>
<endpoint>
<address uri="/api/customers/"></address>
</endpoint>
</send>
<property name="TIME_OUT" expression="get-property('SYSTEM_TIME')" scope="default" type="LONG"></property>
<script language="js">var time1 = mc.getProperty("TIME_IN");var time2 = mc.getProperty("TIME_OUT");var timeTaken = time2 - time1;mc.setProperty("RESPONSE_TIME", timeTaken);</script>
<log level="custom">
<property name="Time Duration in ms:" expression="get-property('RESPONSE_TIME') "></property>
</log>
</onAccept>
<obligations></obligations>
<advice></advice>
</entitlementService>
</inSequence>
<outSequence>
<send></send>
</outSequence>
</resource>
<handlers>
<handler class="org.wso2.handler.SimpleOauthHandlerNew">
</handler>
</handlers
</api>
- SimpleOauthHandlerNew:
package org.wso2.handler;
import java.util.Map;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.axis2.transport.http.HttpTransportProperties;
import org.apache.http.HttpHeaders;
import org.apache.synapse.ManagedLifecycle;
import org.apache.synapse.MessageContext;
import org.apache.synapse.core.SynapseEnvironment;
import org.apache.synapse.core.axis2.Axis2MessageContext;
import org.apache.synapse.rest.AbstractHandler;
import org.wso2.carbon.identity.oauth2.stub.OAuth2ServiceStub;
import org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub;
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationRequestDTO;
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationRequestDTO_OAuth2AccessToken;
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationResponseDTO;
public class SimpleOauthHandlerNew extends AbstractHandler implements ManagedLifecycle {
private String securityHeader = HttpHeaders.AUTHORIZATION;
private String consumerKeyHeaderSegment = "Bearer";
private String oauthHeaderSplitter = ",";
private String consumerKeySegmentDelimiter = " ";
private String oauth2TokenValidationService = "oauth2TokenValidationService";
private String identityServerUserName = "identityServerUserName";
private String identityServerPw = "identityServerPw";
private String oAuth2Service = "oauth2Service";
@Override
public boolean handleRequest(MessageContext messageContext) {
try{
ConfigurationContext configCtx = ConfigurationContextFactory.createConfigurationContextFromFileSystem(null, null);
//Read parameters from axis2.xml
String identityServerUrl = messageContext.getConfiguration().getAxisConfiguration().getParameter(oauth2TokenValidationService).getValue().toString();
String username = messageContext.getConfiguration().getAxisConfiguration().getParameter(identityServerUserName).getValue().toString();
String password = messageContext.getConfiguration().getAxisConfiguration().getParameter(identityServerPw).getValue().toString();
OAuth2TokenValidationServiceStub stub = new OAuth2TokenValidationServiceStub(configCtx,identityServerUrl);
String oauth2ServiceUrl = messageContext.getConfiguration().getAxisConfiguration().getParameter(oAuth2Service).getValue().toString();
OAuth2ServiceStub oAuth2ServiceStub = new OAuth2ServiceStub(configCtx,oauth2ServiceUrl);
ServiceClient client = stub._getServiceClient();
Options options = client.getOptions();
HttpTransportProperties.Authenticator authenticator = new HttpTransportProperties.Authenticator();
authenticator.setUsername(username);
authenticator.setPassword(password);
authenticator.setPreemptiveAuthentication(true);
options.setProperty(HTTPConstants.AUTHENTICATE, authenticator);
client.setOptions(options);
OAuth2TokenValidationRequestDTO dto = new OAuth2TokenValidationRequestDTO();
// dto.set("bearer");
Map headers = (Map) ((Axis2MessageContext) messageContext).getAxis2MessageContext().
getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS);
String apiKey = null;
if (headers != null) {
apiKey = extractCustomerKeyFromAuthHeader(headers);
}
OAuth2TokenValidationRequestDTO_OAuth2AccessToken accessToken = new OAuth2TokenValidationRequestDTO_OAuth2AccessToken();
accessToken.setTokenType("bearer");
accessToken.setIdentifier(apiKey);
dto.setAccessToken(accessToken);
//validate passed apiKey(token)
if (stub.validate(dto).getValid()) {
String user = stub.validate(dto).getAuthorizedUser();
System.out.println(">>>>>>>>>"+user);
user = user.substring(0, user.indexOf('@'));
System.out.println(">>>>>>>>>"+user);
org.apache.axis2.context.MessageContext msgContext;
Axis2MessageContext axis2Msgcontext = null;
axis2Msgcontext = (Axis2MessageContext) messageContext;
msgContext = axis2Msgcontext.getAxis2MessageContext();
msgContext.setProperty("username", user);
return true;
}else{
return false;
}
}catch(Exception e){
e.printStackTrace();
return false;
}
}
public String extractCustomerKeyFromAuthHeader(Map headersMap) {
String authHeader = (String) headersMap.get(securityHeader);
if (authHeader == null) {
return null;
}
if (authHeader.startsWith("OAuth ") || authHeader.startsWith("oauth ")) {
authHeader = authHeader.substring(authHeader.indexOf("o"));
}
String[] headers = authHeader.split(oauthHeaderSplitter);
if (headers != null) {
for (int i = 0; i < headers.length; i++) {
String[] elements = headers[i].split(consumerKeySegmentDelimiter);
if (elements != null && elements.length > 1) {
int j = 0;
boolean isConsumerKeyHeaderAvailable = false;
for (String element : elements) {
if (!"".equals(element.trim())) {
if (consumerKeyHeaderSegment.equals(elements[j].trim())) {
isConsumerKeyHeaderAvailable = true;
} else if (isConsumerKeyHeaderAvailable) {
return removeLeadingAndTrailing(elements[j].trim());
}
}
j++;
}
}
}
}
return null;
}
private String removeLeadingAndTrailing(String base) {
String result = base;
if (base.startsWith("\"") || base.endsWith("\"")) {
result = base.replace("\"", "");
}
return result.trim();
}
@Override
public boolean handleResponse(MessageContext messageContext) {
return true;
}
@Override
public void init(SynapseEnvironment synapseEnvironment) {
}
@Override
public void destroy() {
}
}
In browser im getting
XMLHttpRequest cannot load /CustomerApi?limit=10&offset=0. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://172.250.46.250:8095' is therefore not allowed access.
Please provide me a solution to call the Rest end point from the client. Thanks in advance.
It's ages since this question is asked but not answered. I had the same issue and was stuck with it for few days and thought adding my findings.
One way to add CORS support is to expose your API via WSO2 API Manager and configure CORS support there https://docs.wso2.com/display/AM200/Enabling+CORS+for+APIs
With WSO2 EI, easiest way to add CORS support for your API is to set a HTTP header before the response is sent back.
Eg: