I'm trying to communicate to Google Calendar API.
The API only accepts requests from a specific referrer, e.g.: www.mysite.com/calendar/events.asp
But sometimes the URL includes querystring parameters, e.g.:
www.mysite.com/calendar/events.asp?message=eventAddedSuccessfully&id=50
The API rejects requests from the above URL, and returns this message:
"The referrer www.mysite.com/calendar/events.asp?message=eventAddedSuccessfully&id=50 does not match the referrer restrictions configured on your API key. Please use the API Console to update your key restrictions."
How can I send an AJAX request with only the path in the URL as the referrer?
Thanks
Change your restriction to cater the context path of the domain, it may be specific to that page (and possibly treats it differently with parameters) and causes the issue you're encountering.
www.mysite.com/*
or
www.mysite.com/calendar/*
Hopefully this will resolve the issue.
Related
I'm building an MVC web app that uses the openID Connect hybrid flow to authenticate with Identity Server 3. The MVC web app contains jQuery scripts to get async JSON data from een ApiController. That ApiController is part of the same MVC web app.
I don't want that everyone is able to access the data from the API, so I want to secure the API as well. I added an [authorize] attribute to the ApiController. When requesting the API with a JQuery ajax request I get the following error message:
XMLHttpRequest cannot load
https://localhost:44371/identity/connect/authorize?....etc.
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:13079' is therefore not allowed
access. The response had HTTP status code 405.
But, when I do a request to the API method directly in browser, I will be correct redirected to the Login page of Identity Server..
So, what's exactly the problem here? I read something about that requesting the /authorize endpoint is not allowed via 'back-channel', but I don't understand what's the difference between 'front-channel' and 'back-channel'. Is it possible that I mixed up the wrong OAuth flows? Is the Hybrid flow not the correct one maybe?
I also find out that the API is often a seperate app, but is it always neccessary / best-practice to build a seperate API app that for example requires a bearer token?
Please point me in the right direction about this.
The authorize method on your identity server does not allow ajax calls. Even specifying CORS headers is not going to help you in this particular case. Perhaps you could return a forbidden response instead of a redirect and manually redirect the client to the desired location via window.location
You need to allow your IdentityServer to be accessed from other domains, this is done by allowing "Cross Origin Resource Sharing" or CORS for short. In IdentityServer the simplest way to allow this is in your Client configuration for your Javascript Client, see this from the IdentityServer docs on CORS:
One approach to configuing CORS is to use the AllowedCorsOrigins collection on the client configuration. Simply add the origin of the client to the collection and the default configuration in IdentityServer will consult these values to allow cross-origin calls from the origins.
The error you're seeing is the browser telling you that when it asked IdentityServer if it allows requests from your Javscript client, it returned a response basically saying no, because the origin (http://localhost:13079) was not specified in the "Access-Control-Allow-Origin" response header. In fact that header wasn't in the response at all meaning CORS is not enabled.
If you follow the quickstart for adding a JavaScript client from the docs here all the necessary code is detailed there that you need for the Client config and to setup IdentityServer to allow CORS.
I am newbie to website security and currently trying to understand Same-Origin-Policy in some depth.
While there are very good posts on stackoverflow and elsewhere about the concept of SOP, I could not find updated information on whether chrome and other browsers allow cross-domain XHR post requests to be 'sent' from the first place.
From this 5 year old post, it appears that chrome allows the request to pass through to the requested server but does not allow reading the response by the requester.
I tested that on my website trying to change user info on my server from a different domain. Details below:
My domain: "www.mysite.com"
Attacker domain: "www.attacker.mysite.com"
According to Same-Origin-Policy those two are considered different Origins.
User (while logged in to www.mysite.com) opens www.attacker.mysite.com and presses a button that fires a POST request to 'www.mysite.com' server...The submitted hidden form (without tokens in this case) has all the required information to change the user's info on 'www.mysite.com' server --> Result: CSRF successful attack: The user info does indeed change.
Now do the same but with javascript submitting the form through JQuery .post instead of submitting the form--> Result: Besides chrome giving the normal response:
No 'Access-Control-Allow-Origin' header is present on the requested
resource
, I found that no change is done on the server side...It seems that the request does not even pass through from the browser. The user info does not change at all! While that sounds good, I was expecting the opposite.
According to my understanding and the post linked above, for cross-domain requests, only the server response should be blocked by the browser not sending the post request to the server from the first place.
Also, I do not have any CORS configuration set; no Access-Control-Allow-Origin headers are sent. But even if I had that set, that should apply only on 'reading' the server response not actually sending the request...right?
I thought of preflights, where a request is sent to check if it's allowed on the server or not, and thus blocking the request before sending its actual data to change the user info. However, according to Access_Control_CORS , those preflights are only sent in specific situations which do not apply to my simple AJAX post request (which includes a simple form with enctype by default application/x-www-form-urlencoded and no custom headers are sent).
So is it that chrome has changed its security specs to prevent the post request to a cross domain from the first place?
or am I missing something here in my understanding to the same-origin-policy?
Either way, it would be helpful to know if there is a source for updated security measures implemented in different web browsers.
The XMLHttpRequest object behavior has been revisited with time.
The first AJAX request were unconstrained.
When SOP was introduced the XMLHttpRequest was updated to restrict every cross-origin request
If the origin of url is not same origin with the XMLHttpRequest origin the user agent should raise a SECURITY_ERR exception and terminate these steps.
From XMLHttpRequest Level 1, open method
The idea was that an AJAX request that couldn't read the response was useless and probably malicious, so they were forbidden.
So in general a cross-origin AJAX call would never make it to the server.
This API is now called XMLHttpRequest Level 1.
It turned out that SOP was in general too strict, before CORS was developed, Microsoft started to supply (and tried to standardize) a new XMLHttpRequest2 API that would allow only some specific requests, stripped by any cookie and most headers.
The standardization failed and was merged back into the XMLHttpRequest API after the advent of CORS. The behavior of Microsoft API was mostly retained but more complex (read: potentially dangerous) requests were allowed upon specific allowance from the server (through the use of pre-flights).
A POST request with non simple headers or Content-Type is considered complex, so it requires a pre-flight.
Pre-flights are done with the OPTIONS method and doesn't contain any form information, as such no updates on the server are done.
When the pre-flight fails, the user-agent (the browser) terminate the AJAX request, preserving the XMLHttpRequest Level 1 behavior.
So in short: For XMLHttpRequest the SOP was stronger, deny any cross-origin operations despite the goals stated by the SOP principles. This was possible because at the time that didn't break anything.
CORS loosened the policy allowing "non harmful" requests by default and allowing the negotiation of the others.
OK...I got it...It's neither a new policy in chrome nor missing something in SOP...
The session cookies of "www.mysite.com" were set to "HttpOnly" which means, as mentioned here, that they won't be sent along with AJAX requests, and thus the server won't change the user's details in point (4).
Once I added xhrFields: { withCredentials:true } to my post request, I was able to change the user's information in a cross-domain XHR POST call as expected.
Although this proves the already known fact that the browser actually sends the cross-domain post requests to the server and only blocks the server response, it might still be helpful to those trying to deepen their understanding to SOP and/or playing with CORS.
I am trying to hit USPS address validation API by AJAX call and I am getting 'Cross-Origin Request Blocked' error.
However when I am trying to access the same address though URL, I am getting the results.
Has this error something to do with approval thing?
The id I am using for this has been approved and I am able to get the result by the API through URL.
I want to access it though scripting. Please help.
Any help would be appreciated.
Thanks in advance.
I think the way you might want to do this is to have the Ajax requests go to your web server -- the same HTTP server where the page came from. And then your server-side program (in PHP, or Python or whatever you're using) relays the request to the USPS server.
Making the request browser-side, from Ajax directly to the USPS server, is just the kind of suspicious activity (called Cross-Site Scripting) that browsers are learning to block.
CORS could theoretically be one way to unblock a Cross-Origin Request, but in that scheme it would be the USPS API server that ultimately grants that permission for pages from your domain. Tech detail: by inserting an Access-Control-Allow-Origin header in response to a request with an Origin header in the Ajax back-and-forth.
As the title may possibly suggest, I'm wondering what's more secure for AJAX requests: POST or GET. I can't work out which is better because they're both hidden from the user due to the URI being sent via. AJAX, not in the URL bar.
Thanks,
James
Neither add any security against either man-in-the-middle attacks or the end user. Both can be intercepted and tampered with using Wireshark, Firebug, or other tools.
If you want security against interception, you can use HTTPS. That does not prevent the user from sending requests manually, though.
It's almost trivially easy to inspect the contents of both post and get values. Your best bet, if you do not want the user to be able to get at that data directly, is to encrypt it, and / or send it over ssl.
There are no security differences between POST and GET used in AJAX. They are not hidden from the user - a simple tool like Fiddler would allow the user to see those requests. the payload in both is in plain text (ie, as your script created it). The only difference is that POST payload is in the body of the request and GET payload is in the query params of the URL.
They are not hidden from the user at all; install FireBug on FireFox and they are able to see the URI. Your choice of using GET and POST depends on the data sent; and if you going by REST standards, depending on the operation.
Treat an AJAX call as you would with information coming from the client through a form and through the address bar : Verify and sanctify.
They can view the page source and see where your target URL is and what parameters are being passed either way.
I would like to make an ajax call to a different server (same domain and box, just a different port.)
e.g.
My page is
http://localhost/index.html
I would like to make a ajax get request to:
http://localhost:7076/?word=foo
I am getting this error:
Access to restricted URI denied (NS_ERROR_DOM_BAD_URI)
I know that you can not make an ajax request to a different domain, but it seem this also included different ports? are there any workarounds?
Have a certain page on your port 80 server proxy requests to the other port. For example:
http://localhost/proxy?port=7076&url=%2f%3fword%3dfoo
Note the url encoding on the last query string argument value.
You could use JSONP. This is where you specify a callback with the request, the response from your ajax request gets wrapped with the callback function name. Rather than using XmlHttpRequest you insert a tag into the HTML document with the URL. Then when the response is retrieved the callback function is called, passing the data as a parameter.
Check this blog post out for an example
This is a browser restriction. All javascript calls must be to the same server and port of the home of the script. This will require something server-side to get around. I.E. have the process at localhost forward the request to localhost:7076.
It sucks, but it's necessary... Basically what you're going to need to do is proxy your AJAX request through a local proxy - some server side script / page / whatever on the same domain you're on - receive the call and forward it on to the other resource server-side. There might be some IFRAME tricks you could do but I don't think they work very well...could be wrong though, been awhile.