I've built a simple SignalR hub that lives within a WebAPI service, I've included all the required CORS attributes on both WebAPI and SignalR. My WebAPI endpoints are all working as expected but SignalR isn't.
I've tried all I can think of and all I can find online but nothing works, I already tried this answer, and this other to no solution.
My SignalR extension method looks like this
public static IAppBuilder UseSignalrNotificationService(this IAppBuilder app)
{
var config = new HubConfiguration();
config.Resolver = new HubDependencyResolver();
config.EnableDetailedErrors = true;
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR(config);
return app;
}
And I even tried adding the response headers on all requests using the Web.config but I allways get the same error:
XMLHttpRequest cannot load https://MyApplicationServer/notifications/signalr/negotiate?clientProtocol=1.5&access_token=&connectionData=. A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'MyOriginService' is therefore not allowed access. The credentials mode of an XMLHttpRequest is controlled by the withCredentials attribute.
After more research and fiddling with the server side of the problem, I ran into this answer and found the error to be with the client side of the request. according to this GitHub issue, the "withCredentials" parameter of the request is always set to 'true'. The solution was to call on the client the start method as follows:
$.connection.hub.start({ withCredentials: false }).done(function () { //... }
Are you changing the request somewhere with some kind of global interceptor? For some reason, the XMLHttpRequest starts with withCredentials:true and this is forbidden when the Access-Control-Allow-Origin is set to *.
What about setting the 'Access-Control-Allow-Origin' to 'http://MyApplicationServer'? It's safer than * and will remove your problem at source.
Related
I am getting CORS blocked regardless of what I allow. It only yells at me for my POST route, my GET routes it allows just fine. I consistently get
Access to XMLHttpRequest at 'https://simple-startup-survey-backend.herokuapp.com/client_answers' from origin 'http://simple-startup-survey.surge.sh' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I am using an AJAX to communicate with an EXPRESS server. I allow all requests with the wildcard operator. I have tried sending {crossDomain: true} with my request.
//This is my backend in app.js
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET,POST,DELETE,PATCH,PUT");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
// This is my front end AXIOS call POST request. This is what is //triggering the CORS block
storedData = storedData.concat(storedData2)
axios.post('https://simple-startup-survey-backend.herokuapp.com/client_answers', {crossDomain:true}, storedData,)
.then(function(response){
console.log(response.data , ' save success')
localStorage.setItem("storedData", JSON.stringify(storedData))
window.location.href = "../AnalysisPage/analysis.html";
}).catch()
})
// This is my perfectly functional GET request. It does a bunch of //stuff after this in the .then, but I don't think that is relevant to //this issue
function getgeneralQuestions(){
axios.get('https://simple-startup-survey-backend.herokuapp.com/questions/balanceSheet')
.then(function (response) {
Every damn Google search result on the planet says that what I have in regards to my back end should work. I am using vanilla JS, no JQUERY.
Any help greatly appreciated!
back end Github: https://github.com/TuckerNemcek/SimpleSurveyBackend
front end Github: https://github.com/TuckerNemcek/SimpleStartupSurveyProject
I am running into a similar issue.
My hunch is that surge.sh does not have cors enabled on its server.
My website is actually making the request correctly.
Afterward there is an error and the data is not shown.
Edit: Solved - - - -
Actually, just solved this for myself!
This is my script for publishing.
yarn build; cp build/index.html build/200.html; echo '*' > build/CORS; surge build appname.surge.sh
here is an article about enabling cors for surge.sh https://github.com/surge-sh/example-cors
Also when making changes make sure you are in a new incognito tab each time or go to the network tab on dev tools and Disable cache otherwise your app might be lying to you and thing cors is not enabled when it in fact is enabled.
I'm having an issue trying to get a token from my server on an Angular 5 project. My POST request is never sent and the server returns 400 Bad Request and shows the following in the console:
My understanding is that I need to configure the OPTIONS request in CORS to allow the cross-origin request, but I feel like I've tried every solution there is out there without any success.
As far as what I have tried so far, in my Web.config I have this:
And I enabled CORS globally in my WebApiConfig.cs:
I even implemented the solution suggested at https://www.stevefenton.co.uk/2012/11/using-cors-with-asp-net-web-api/
Here is the call I am making in my Angular 5 project:
userAuthentication(userDetails: LoginUser): Observable<LoginUser> {
var data = "username=" + userDetails.username + "&password=" + userDetails.password + "&grant_type=password";
var reqHeader = new HttpHeaders({ 'Content-Type': 'application/x-www-form-urlencoded', 'No-Auth': 'True' });
return this.http.post<LoginUser>(this._baseUrl + 'Token', data, { headers: reqHeader })
.pipe(
catchError(this.handleError)
)
}
When I make the call using POSTMAN, everything runs smoothly and I get my access_token.
I've managed to resolve this issue. I needed to add Microsoft.Owin.Cors with Microsoft.AspNet.Cors and Microsoft.AspNet.WebApi.Cors.
I then had to add app.UseCors(CorsOptions.AllowAll); to my Startup.cs file:
…and remove the customHeaders from between the system.webserver tags in Web.config:
All is running smoothly now.
Note: It's important to note that when enabling CORS on your WebApiConfig.cs, if you have followed the previous steps I have shown, you must enable it like this:
…and not like this:
If you do, you will get an error stating your header contains multiple values and therefore will deny your Origin access.
So I've read up on all the previous questions on this, but following the steps don't seem to be working for me. I'm getting the "Origin * is not allowed by Access-Control-Allow-Origin", but that doesn't make sense to me. If I open the same request in Chrome in it's own tab, and look at the network tab, I see the following CORS headers intact. Also, the hubs generate just fine. I'm using Web API, .NET 4.5, and the rc2 of SignalR. I also tried removing the Allow-Credentials in the web.config, but that didn't help either.
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:x-requested-with,X-CustomAuth,Content-Type,X-Impersonate
Access-Control-Allow-Methods:GET,OPTIONS,PUT,DELETE,HEADER
Access-Control-Allow-Origin:*
I've also set jQuery.support.cors to true, even though it was already as true, I'm using JQuery 1.9, and here's my connection to the server and hub:
jQuery.support.cors = true;
$.connection.hub.url = 'http://myserver/api/signalr';
$.connection.hub.start({ transport: 'longPolling', xdomain: true });
I've also tried this to connect, both with same issue.
$.connection('http://myserver/api/signalr/echo').start(function () {
console.log('Connected');
$.connection.hub.start().done(function() {
$log.info('Connected to hub.');
});
});
The * value cannot be used with the Access-Control-Allow-Origin header if Access-Control-Allow-Credentials is true. Try either one of the following:
Drop the Access-Control-Allow-Credentials header entirely.
Change the value of the Access-Control-Allow-Origin from * to the actual value of the Origin header.
#1 might be easier to do, but #2 is required if you need to support cookies.
According to the official doc, you should NOT be using jQuery.support.cors
Don't set jQuery.support.cors to true in your code.
Link to the official doc: official doc
In my XPage I have a xe:djxDataGrid (dojox.grid.datagrid) which uses xe:restService which seems to use dojox.data.JsonRestStore.
Everything works fine without proxy but my client accesses the application via a proxy because of corporate policy. After a user updates data in the DataGrid it shows old values when accessed behind the proxy.
When the REST Control/JsonRestStore sends an ajax GET request to get data, there is no Cache-Control parameter in request headers. And Domino does not place Expires parameter in the reponse headers. I believe that's why the old version of the GET request gets cached by the proxy.
We have tried to disable cache in browsers but that does not help which indicates the proxy is caching the requests.
I believe this could be solved either by:
Setting Cache-Control parameter in request headers OR
Setting Expires parameter in response headers
But I haven't found a way to set either of these. For the XPage Domino sets Expires:-1 response header but not for the ajax GET request which is:
/mypage.xsp/?$$viewid=!ddrg6o7q1z!&$$axtarget=view:_id1:_id2:callback1:restService1
This returns the JSON data to JsonRestStore and gets cached by the proxy.
One options is to try to get an exception to the proxy so requests to this site would bypass the proxy cache. But exceptions are generally not easy to get thru.
Any ideas? Thanks.
Update1
My colleque suggested that I could intercept the xhr GET requests made by dojox.data.JsonRestStore and add a time parameter to the URL to prevent cache. Here is my question about that:
Prevent cache in every Dojo xhr request on page
Update2
#SvenHasselbach has a great solution for preventing cache for all xhrs:
http://openntf.org/XSnippets.nsf/snippet.xsp?id=cache-prevention-for-dojo-xhr-requests
It seems to work perfectly, &dojo.preventCache= parameter is added to the URLs and the requests seem to return correct JSON also with this parameter. But the DataGrid stops working when I use that code. Every xhr causes this error:
Tried with Firefox and Chrome. The first page of data still loads because xhr interception is not yet in place but the subsequent pages show only "..." in each cell.
The solution is Sven Hasselbach's code in the comment section of Julian Buss's blog which needs to be slightly modified.
I changed xhrPost to xhrGet and did not place the code to dojo.addOnLoad. When placed there it was not effective in the first XHR by the DataGrid/Store.
I also removed the headers modification because it overrides existing headers. When the REST control requests data from server with xhrGet the URL is always the same and rows requested are in HTTP header like this:
Range: items=0-9
This (and other) headers disappear when the original code is used. To just add headers we would have take the existing headers from args and append to them. I didn't see a need for that because it should be enough to add the parameter in the URL. Here is the extremely simple code I'm using:
if( !(dojo._xhrGet )) {
dojo._xhrGet = dojo.xhrGet;
}
dojo.xhrGet = function (args) {
args['preventCache'] = true;
return dojo._xhrGet(args);
}
Now I'm getting all rows and all XHR Get URLs have &dojo.preventCache= parameter which is exactly what I wanted. Next we'll test in customer environment to see if this solves their problem.
Update
As Julian points out in his blog I could also use a Web Site Rule to set Expires or cache-control http response headers.
Update
The customer reports it's working now for them!
Got this error message:
Refused to set unsafe header "Origin"
Using this code:
function getResponse() {
document.getElementById("_receivedMsgLabel").innerHTML += "getResponse() called.<br/>";
if (receiveReq.readyState == 4 || receiveReq.readyState == 0) {
receiveReq.open("GET", "http://L45723:1802", true, "server", "server123"); //must use L45723:1802 at work.
receiveReq.onreadystatechange = handleReceiveMessage;
receiveReq.setRequestHeader("Origin", "http://localhost/");
receiveReq.setRequestHeader("Access-Control-Request-Origin", "http://localhost");
receiveReq.timeout = 0;
var currentDate = new Date();
var sendMessage = JSON.stringify({
SendTimestamp: currentDate,
Message: "Message 1",
Browser: navigator.appName
});
receiveReq.send(sendMessage);
}
}
What am I doing wrong? What am I missing in the header to make this CORS request work?
I tried removing the receiveReq.setRequestHeader("Origin", ...) call but then Google Chrome throws an access error on my receiveReq.open() call...
Why?
This is just a guess, as I use jquery for ajax requests, including CORS.
I think the browser is supposed to set the header, not you. If you were able to set the header, that would defeat the purpose of the security feature.
Try the request without setting those headers and see if the browser sets them for you.
In CORS the calling code doesn't have to do any special configuration. Everything should be handled by the browser. It's the server's job to decide if request should be allowed or not. So any time you are making a request which breaks SOP policy, the browser will try to make a CORS request for you (it will add Origin header automatically, and possibly make a preflight request if you are using some unsafe headers/methods/content types). If the server supports CORS it will respond properly and allow/disallow the request by providing CORS specific response headers like
Access-Control-Allow-Origin: *
Keep in mind that Chrome is very restrictive about 'localhost' host name. (At least it was when I was working with it). Instead use your computer name or assign it another alias in 'hosts' file. So for example don't access your site like:
http://localhost:port/myappname
Instead use:
http://mymachinename:port/myappname
or
http://mymachinealias:port/myappname
For more details please check specification.
Are you working cross-domain?
Try Brian S solution or try this:
instead of setting to localhost just pass anything... and see what happens.
receiveReq.setRequestHeader("Origin", "*");