Salesforce and Angular with separate servers - angularjs

I have two sets of servers:
apache serving up html/js/css pages in the angular flavor
SalesForce backend rest apis serving up Json
Salesforce has OAuth authentication, but it is not letting the javscript even perform an OPTIONS call in order to figure out if it can do the POST call it really wants to:
Is there any way to get around this without a proxy or jsonp?
is the Salesforce APEX Rest API configured wrong? the source domain is already whitelisted...
Update:
so some angular code to make the call:
var config = {
method: 'POST',
url: SalesforceRestApi,
headers: {
Authorization: "OAuth "+authToken,
"Content-Type": "application/pdf"
},
data : caseRequest,
};
var http = angular.element(document.body).injector().get('$http');
http(config).then(function(response){ console.log(response); });
this code here returns the good old Chrome error:
XMLHttpRequest cannot load https://xxx.salesforce.com/services/apexrest/xxx/v1/. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://sample.com' is therefore not allowed access. The response had HTTP status code 401.

Related

cors problem with react js request and jwt

i'm trying to fetch data with react from asp.net core 3.1 so i login with a request and get the jwt token. after that i want to send a request for getting data from api but it cause "preflight request "Access to fetch at 'https://localhost:44328/Address' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
apiAddress.js:24 GET https://localhost:44328/Address net::ERR_FAILED", i work with visual studio localhost as api server and configured startup like below:
//in ConfigureServices
services.AddCors(options =>
{
options.AddPolicy(name: AllowedOrigins,
builder =>
{
builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.SetIsOriginAllowed(hostName => true);
});
});
//in configure
app.UseCors(AllowedOrigins);
my fetch request is like below in reactjs:
const response = await fetch(url, {
'method': 'GET',
'mode': 'cors',
'credentials': 'include',
'headers': {
'Content-Type': 'application/json; charset=utf-8;',
//'Content-Type':'application/x-www-form-urlencoded',
'Authorization':`bearer ${token}`
}
});
and finally my controller is like below:
[ApiController, EnableCors("AllowedOrigins"), Authorize, Route("[controller]")]
public class AddressController : ControllerBase
what is wrong, i must mention other actions without [Authorize] attribute working ok, but action with it not works?!
some one mentioned that i should enable options in iis, but didn't explained how?
You will probably need to enable CORS on IIS. Here are steps how to do.
Open Internet Information Service (IIS) Manager.
Right click the site you want to enable CORS for and go to Properties.
Change to the HTTP Headers tab.
In the Custom HTTP headers section, click Add.
Enter Access-Control-Allow-Origin as the header name.
Enter * as the header value.
Click Ok twice.
Response to preflight request doesn't pass access control check: ....
other actions without [Authorize] attribute working ok, but action with it not works
In this doc, you would find:
A CORS preflight request is used to determine whether the resource being requested is set to be shared across origins by the server. And The OPTIONS requests are always anonymous, server would not correctly respond to the preflight request if anonymous authentification is not enabled.
While hosting on IIS server, you can try to install the IIS CORS module and configure for the site/application to make it work well.
Besides, if you'd like to make it work on local with IIS express, for testing purpose on CORS, you can try to allow anonymous access.
Or run it with kestrel and write custom middleware to correctly respond to the preflight request.

Get method is converted to OPTIONS when hitting fetch api in React js

I am trying to hit below api and requires basic auth username and password and method allowed in this is only get
dispatch(requestBegin());
let apiPath = `xxxx/TEST/appservice/api/app/10/10000127201901`;
return fetch(apiPath, {
method: 'get',
headers : {
"contentType":"application/x-www-form-urlencoded",
"Authorization" : 'Basic '+btoa('xxx:xxx'),
},
})
.then((response) => {
dispatch(getEventsEnds(json));
})
.catch((error) => {
dispatch(getEventsEnds());
});
The error loged in console :
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:2200' is therefore not allowed
access. The response had HTTP status code 405. If an opaque response
serves your needs, set the request's mode to 'no-cors' to fetch the
resource with CORS disabled.
OPTIONS http://xxx/appservice/api/app/10/10000127201901 405 (Method
Not Allowed)
Can anyone please eplain when i m trying to hit get api then why is it showing options
That means your API server does not accept CORS request or requests originating from localhost.
Check out your API documentation but my guess is you won't be able to interact directly with it from your web app.
Your best bet is to use a proxy, you can develop one yourself or use something like node-http-proxy to proxy your API calls. (There are php or python equivalents)
The proxy server will be able to issue the requests and will then forward them to your app.
Suggested further reading: type understanding CORS on google and read more about it.
For local development, check out:
https://github.com/Rob--W/cors-anywhere
This issue occurs when the client api URL and server URL don't match, including the port number. In this case you need to enable your service for CORS which is cross origin resource sharing.
use npm install cors
refer this[refer][1]

CROS OPTIONS request when trying to upload a file with $http angularjs

I'm actually trying to implement a file upload system between my client side angularjs app and my server but i'm having difficulties to implement this feature.
The problem seems to come from the preflight OPTIONS request sent from Chrome.
When I test my route with postman everything work just fine.
Here is a few screen shots of the postman request execution:
First part of postman example
Second part of postman example
As you can see the route has two parameters a library id and a file to be uploaded and an authentification token.
The problems appear when I try to implement an upload feature in my angular web app.Indeed when I call my $http post request a OPTIONS preflight request is sent to my server.This OPTIONS request doesn't seem to have any of the parameters given to the post request it precedes making my authentification middleware (that has the function of validating the user/token) on my server side respond with a 401 error.
More exactly:
XMLHttpRequest cannot load ..... Response for preflight has invalid http status code 401
It seems that those preflight request are made by the browser when say detect a cross origin resource sharing. This is were I hit a brick wall. I cannot seem to understand how to:
- either send the token with the options request to validate this request
- or to bypass this options request to directly send my post request.
my upload function looks like this:
$http({
method: 'POST',
url: 'my-upload-url',
headers: {
'Content-Type': 'multipart/form-data'
},
data: {
library: my-library-id,
file: my-file-to-upload,
token: user-authentification-token
},
transformRequest: function (data, headersGetter) {
var formData = new FormData();
angular.forEach(data, function (value, key) {
formData.append(key, value);
});
var headers = headersGetter();
delete headers['Content-Type'];
return formData;
}
})
.success(function (data) {
})
.error(function (data, status) {
});
My questions are:
Is there a way to actually send my user token in the OPTIONS request to make it valid server side?
Is there a way of formatting my post request (header/data/params) to make it bypass this preflight browser request?
Is the formatting of my post request wrong in any way making it trigger the OPTIONS request from Chrome?
Thank you in advance for your help.
Martin
In cors, the OPTIONS method is used to tell the server what will your request do. The server must handle the OPTIONS correctly so your main request will send normally. The browser will send the OPTIONS request automatically when your request is a complex cross origin request.
To bypass the OPTIONS request your request should be POST and GET and content-type must be application/x-www-form-urlencoded, multipart/form-data, or text/plain and the headers only contain Accept, Accept-Language and Content-Language.
Your request is not wrong. The reason is that your request is a cross origin request and it isn't a simple request.
So the best way to solve this problem is to make your server handle the cors request correctly.
For express you can use https://github.com/expressjs/cors
see more: cors-mdn cors-w3c

Http status 405 while making $http get request

I am making ajax get request using angular js $http service to yahoo finance rest api however i am getting http status code 405 in response.
below is the complete stack trace.
index.html#/tab/stock:1 XMLHttpRequest cannot load http://finance.yahoo.com/webservice/v1/symbols/SUZLON.NS/quote?format=json&view=detail.
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin'
header is present on the requested resource.
Origin 'http://localhost:8080' is therefore not allowed access.
The response had HTTP status code 405.
Below is my code to make ajax call.
var config = {
headers : {
'Access-Control-Allow-Origin' : '*',
'Accept' : 'application/json;odata=verbose',
"HOST" : "finance.yahoo.com"
}
};
var promise = null;
promise = $http.get('http://finance.yahoo.com/webservice/v1/symbols/SUZLON.NS/quote?format=json&view=detail',config);
return promise;
I am able to make ajax call to google finance api but yahoo finance api is failing.
Do i need to set any header my config object ?
Or is it something different at Yahoo Rest API side which is returning Http 405 ?
Below code for google api call is working fine without setting any header.
getNseQuote : function(nseScriptCode) {
console.log("Inside nseScriptCode : " + nseScriptCode);
var promise = null;
promise = $http.get('http://www.google.com/finance/info?q=NSE:' + encodeURIComponent(nseScriptCode));
return promise;
}
You can use this extension for chrome link. It allows you to do cross-domain request..Also before you integrate the API with your application test the API URL, see if its working using third party tool like Postman which is best for testing API calls..
Regarding your error
"Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin'
header is present on the requested resource." what it means is that the server is not configured to handle pre-flight request.Pre-flight request is request done by browser in special cases such as when you are requesting data from different domain(when you are doing a request other than GET/POST and using any custom header in your request etc.) for security purpose only (I suppose)..
So, In you case you should use proxy-server which you can make using any open source packages available...In my case I was using node-http-proxy.The browser calls the proxy server and the proxy server fetches the data from the actual server and returns it to the browser..it is easy to make with a little bit of tinkering...

Angular making a CORS request

I am very confused. I am trying to use a web service to obtain data. When I put the url into the browser, it works great and returns the json I was expecting.
If angular is a client side framework, why does it not succeed when making the exact same request? The is coming from my browser but the receiving domain still barfs on it.
What am I missing?
Whoever owns the service needs to configure CORS (Cross Origin Resource Sharing), to either allow your particular domain access to the service or to allow all domains to access the service. You then need to configure the correct headers to send your origin and credentials to the origin you are trying to access the service on when making the request so that it can decide if it's gonna let you hit that endpoint or reject the request. Here's the go-to website for an overview and setup guide for CORS: http://enable-cors.org/.
You also need to set the withCredentials flag to true on the http request config object.
Ex.
$http({
url : 'url of service',
method : "POST",
data : {
test : name
},
withCredentials : true,
headers : {
'Content-Type' : 'application/json; charset=utf-8'
}
});
More about the angular configuration for this can be found on the angular docs website for the $http service.

Resources