Much of this is taken from the
same origin and
CORS
articles at Mozilla, which provide much more information.
- A web page is built from many resources of different types: HTML,
images, CSS, Javascript, etc. These are loaded from various locations.
- The base page loads these resources by URL, which means they could be
anywhere.
- In classic web, this no big deal. But as the web is used for more
things, this starts to create problems. One in particular is
called a Cross-Site Request Forgery (CSRF).
- When a browser sends a request to server S, all the cookies
that came from S go along with that
request. Hence, the request carries all relevant credentials.
- When a user is logged in to an account, any request from the browser
will be treated as authorized.
- Cookies are sent only back to their origin, so
if Joe, while logged into site bank, visits some other site,
not-bank in a different tab or window, the bank cookies are not
sent to not-bank.
- But some Javascript on the non-bank page
could build and send a request to bank. These will send the
cred cookies back to bank.
- Bill, who either works at non-bank, or just hacked it, could then
use Javascript to construct and send a request to bank that
transfers $1000 from Joe to Bill.
- Since it's going to bank bank's cookies, which will treat the request
as authorized.
- A classic source of CSRF is social media and comment boards.
- User A posts a comment, whose text will displayed to other users on
the social media site.
- The attacker manages to embed some JavaScript which is run in the
browser of User B. (Who might just be logged into bank.)
- The media site is responsible to filter uploads so this cannot
happen, but:
- Some don't do a good job.
- Software to clean the input can have bugs.
- Hackers can be clever. (You'd think they'd find honest work for
that brain. At least, that's what my mother would have said.)
- To help limit this, browsers implement a Same-Origin Policy.
- A page (or other resource) is limited in its access to resources
from different origins.
- An origin is defined as the triple of protocol, port, and hostname.
- Obviously, different host names give different origins.
- Http and https access to the same host are different origins.
- An IP address produces a different origin than a host name that
resolves to it.
- File urls are different origins from any network location.
Depending on the browser, all origins are different from
other file origins. For some reason.
- The path is not part of the origin.
- The Javascript at origin at not-bank would be forbidden
to fetch a page with origin at bank.
- An origin is the triple of protocol, port and host. (But not path.)
- Not as simple as it sounds.
- Pages created by Javascript generally inherit the origin of the script.
(That is, starting with Window.open(), not just filling in some
page with an empty body.)
- Special URLs like about:, and file: URLs present some subtleties.
- Javascript can adjust its own origin by removing subdomains (so
foobar.fred.com can become fred.com. (Apparently,
this capability is deprecated.)
- A cross-origin request can be generated by HTML, CSS, or JavaScript.
- Cross-origin linking, including form submission
is generally allowed.
- Embedding is allowed
- Img and other media
- Script tag with src attribute.
- Linking a style sheet, though the response must have a correct
Content-Type header.
- Even iframe, which I guess is isolated so it's security is
more like linking.
- JavaScript fetch and the older XMLHttpRequest are not embedding,
and are subject to origin rules.
That is why the page at a file URL cant make AJAX requests
to a server. But it does not explain the infuriating fact
that browsers provide no control to disable this restriction
for testing purpose.'
- Full rules are complicated.
- Sometimes you want to allow a cross-origin transaction which the
policy would forbid.
Third-party services: authentication, payment, etc.
- Cross-Origin Resource Sharing (CORS) is an HTTP extension to control
such access.
- The server may send a Access-Control-Allow-Origin header
to permit a page to be loaded from a different origin.
The value of the header can be a origin, *, or null.
- An origin is like https://www.this.place, which gives
protocol, host and (implicitly) port.
- I suppose you could supply a port.
- You can only give one origin. If you want to allow the
source of the request, you need to give its origin.
- The * is supposedly any origin
- Doesn't seem to be in practice.
- It is documented to exclude requests that are marked as containing
credentials. Must use the specific origin.
- The script you are using for the calendar assignment sends
Access-Control-Allow-Origin *
- null seems to mean “other stuff” and you're not supposed to use it.
- Some requests are not “simple,” and must be “pre-flighted”
- Browser sends an HTTP options request first, to see if the
server will accept the origin of the request.
- Only sends the request proper if the server seems happy.
- Most requests are simple. You lose simplicity when you use
a method other than GET, HEAD or POST, or go beyond a short list
of conventional request headers.
- Credentialed request. Not sure all of this is right.
- A Credentialed request is one that contains credentials.
- AFAIK, in practice that just means an option is set in the fetch
or XMLHttpRequest call.
- The brower uses strictor CORS rules: The server must respond with
the Access-Control-Allow-Credentials header.
- Without the flag, the client won't send things that could be
credentials, such as cookies, to a different origin. (Probably will
exclude any cookies, whatever they hold.)