CORS issue with SignalR - Origin not allowed - asp.net-web-api

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

Related

SignalR responses overwriting headers

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.

GroceryCRUD add, edit buttons not working when enabling CodeIgniter CSRF protection

I am using GroceryCRUD 1.5.0 with CodeIgniter 2.2.0.
When enabling CodeIgniter's internal CSRF protection with:
$config['csrf_protection'] = TRUE;
in application/config/config.php, then the GroceryCRUD auto-generated action buttons (edit, view) and links (add) does not work anymore.
It seems that the CSRF token is not passed along in the Ajax calls (confirmed with Firebug). It is possible to use this CodeIgniter feature with GroceryCRUD?
I finally managed to solve my problem. Two options are available:
The easy way:
Set:
$config['grocery_crud_dialog_forms'] = false;
in application/config/grocery_crud.php.
This option works well without CSRF protection enabled (that is, it can be set to true to produce more elegant forms), but fails when set if no code modifications are done in the javascript.
The elegant way:
If we want to use:
$config['grocery_crud_dialog_forms'] = true;
in application/config/grocery_crud.php to have the cute forms, then:
include the jquery.cookie plugin in pages with forms
add this code to your JS files to auto-magically insert the CSRF token in all ajax POST calls:
$(document).ready(function() {
var csrf_token= $.cookie('csrf_cookie_name');
$.ajaxSetup({
data: {
'csrf_test_name' : csrf_token
}
});
});
I hope this will help someone else.
Just in case someone has the same error: For CI 3.0.1 and GroceryCRUD 1.5.1, Cookies are properly sent with AJAX requests, however because the token changes, only the first request will work.
To always use the same token, set (in application/config/config.php):
$config['csrf_regenerate'] = FALSE;
Edit: Manual for reference: http://www.codeigniter.com/user_guide/libraries/security.html#cross-site-request-forgery-csrf

AJAX call appears cached for about 2 minutes on Mac

I have an Ajax widget that monitors the status of a connection on a web page, and alerts the user when the server can no longer be reached. It works on Windows 7, but fails on Mac OSX 10.5.8 (both Safari and Firefox).
The crucial code is here:
(function(e){
e.fn.checknet=function(config){
function checkConnection(config){
e.ajax({
url:config.checkURL,
cache:false,
success:function(){
window.checknet.conIsActive=true
},
error:function(){
window.checknet.conIsActive=false
},
complete:function(){
if(window.checknet.conIsActive){
connectionExtablished()
}
else{
connectionLost()
}
}
})
setTimeout(
function(){checkConnection(config)},
config.checkInterval
)
}
}
})(jQuery);
I'm calling it every five seconds. When I shut down the server, Windows browsers do indeed notice within five seconds. However, the browsers on my Mac need about two and a half minutes.
From other questions, I gather that caching can be an issue. However, I've tried inserting parameters:"defeatcache=" + new Date().getTime() to the Ajax call and $.ajaxSetup({ cache: false }); before the Ajax call; neither works.
Does anybody have any suggestions for how I can get my Mac browsers to notice the downed connection sooner?
As mentioned in the comment and here How to disable Ajax caching in Safari browser?, you need to append the paramater to the URL, I'm not sure what this bit is doing parameters:"defeatcache=" but the way I have always used it is on the url:
url = url + '&nocache=' + new Date().getTime();
To modify your example where checkURL is the plain url unedited it should be
url:config.checkURL + '&nocache=' + new Date().getTime(),
If the above still does not work you want to add no-cache headers to the URL you are trying to access - for example if the url you were accessing was called "status.php" then you could try adding no-cached headers to the status.php page itself:
header('Cache-Control: no-cache, no-store, must-revalidate'); // HTTP 1.1.
header('Pragma: no-cache'); // HTTP 1.0.
Obviously this code above (for PHP) would be different depending on your sever side language (taken from & more examples for other server side languages here: einternals)
when you make your .ajax() call use the option cache: false
.ajax(
{url: 'http://...',
cache: false });
or
before your ajax call use ajaxSetup
$.ajaxSetup({ cache: false });
I used to disable caching in the response's header. So in the service that provides the response, look into setting various fields to disable caching from that end of the call. Sorry I don't have any ready examples!! Hope this helps.

Refused to set unsafe header "Origin" when using xmlHttpRequest of Google Chrome

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", "*");

jQuery and Ajax with json - fails in IE

I'm using jQuery (1.7.0) to make a json/ajax call to Spotify. The following code works fine in Chrome and Firefox, but causes an error (Error: Access is denied.) in IE.
$.ajax({
url: 'http://ws.spotify.com/lookup/1/.json',
type: 'GET',
dataType: 'json',
cache: true,
data: {
uri: "someartist",
extras: "album"
},
success: successfn,
error:function(xhr, status, errorThrown) {
alert("networking error: "+errorThrown+'\n'+status+'\n'+xhr.statusText);
}
});
The success function is called in Chrome and FF, but the error function is called in IE with the above message. I have set cors to true: jQuery.support.cors = true;.
It works on Chrome and FF both locally and on my server, it works in IE locally but not on the server. Changing cache: false causes problems at the spotify end - doesn't line additional parameters, so I get a "bad request" error.
Grateful for any pointers.
Thanks
Abo
You are relying on the spotify url to give a Access-Control-Allow-Origin:* in their header to allow cross domain requests from all domains. Internet explorer however doesn't support this, so it gives access denied.
access-control-allow-origin explained. (TLDR: Servers may allow cross domain ajax in their headers)
If you need this to work in IE, you could use spotify's JSONP API if they have one or make the AJAX request in flash, which works in all browsers and passes the requests response data to your javascript.
The above answer about using jsonp is correct; I want to add:
Don't set
jquery.support.cors = true;
I'm not sure why so many questions begin by stating they took that step. This property is meant to be read to find out if the browser supports CORS. You should only override it if you know differently, and in my experience it's accurate for all major browsers. Setting it to true doesn't enable the browser to use CORS, it just denies you the info that CORS is going to fail.
http://api.jquery.com/jQuery.support/
can you give an example of returned data?
at a /guess/, it either has something to do with the filename ".json", or the JSON returned has something weird about it.
I'm surprised this works on Chrome or Firefox. You shouldn't be able to run cross-domain JSON requests.
If Spotify API supports it, you should use JSONP in order to access resources from other domains.
Also see: No response from jQuery ajax call
I don't see this working in FF. You can't make cross-domain Ajax calls. So I'm not sure what's going on when you say that it works in FF. But I just tried the following in FF and I got the error. So all you can do is make the call on the server side and then include the results in your page.
http://jsfiddle.net/2XWGn/

Resources