CORS (Cross-Origin Resource Sharing) 23.2
Cross-Origin Resource Sharing is a browser technology specification that defines ways for a web server to allow its resources to be accessed by a browser application from a different origin domain. Such access would otherwise be forbidden by the same origin policy. CORS defines a way in which the browser and the server can interact to determine whether to allow the cross-origin request. It is a compromise that allows greater flexibility, but is more secure than simply allowing all such requests.
The CORS standard works by adding new HTTP headers that allow servers to serve resources to permitted origin domains. Browsers support these headers and enforce the restrictions they establish. Additionally, for HTTP request methods that can cause side-effects on user dataβin particular, for HTTP methods other than GET, or for POST usage with certain MIME typesβthe specification mandates that browsers βpre-flightβ the request, soliciting supported methods from the server with an HTTP OPTIONS request header, and then, upon βapprovalβ from the server, sending the actual request with the actual HTTP request method. Servers can also notify clients whether "credentials" (including Cookies and HTTP Authentication data) should be sent with requests.
CORS can be used as a modern alternative to the JSONP pattern. While JSONP supports only the GET request method, CORS
also supports other types of HTTP requests. Using CORS enables a web
programmer to use XMLHttpRequest
, which supports a
better error handling than JSONP. CORS is
supported by most modern web browsers. However, JSONP works on legacy browsers which preclude
CORS support.
CORS and the Open Commerce API
The Open Commerce API supports the CORS specification.
If an API request contains an Origin header,
the origins in the header are verified against a list of
allowed origins. The list can be configured in Business Manager Open Commerce API Settings on a per site
and client application basis. If all the origins in the header match the
configured origins, the API confirms the origins by returning all allowed
origins in response header
Access-Control-Allow-Origin
. Additionally, the API
returns the response header
Access-Control-Allow-Credentials
with value
"true", which notifies the client to send also cookies. If an origin is
not defined in the allowed origins list, the API does NOT add the
Access-Control-Allow
headers to the response. This
is true for GET and HEAD requests. For PATCH, POST, PUT, and DELETE
requests, the API returns a 401 fault of type
UnauthorizedOriginException
and ensures that there
is no processing on the server side.
"Preflighted" requests first
send an HTTP OPTIONS request header to the resource on the other domain;
this determines whether the actual request is safe to send. Cross-site
requests are preflighted because the requests may affect user data. In
particular, a request is preflighted if it uses methods other than GET or
POST. A request is also preflighted if the POST method is used to send
request data with a Content-Type other than
application/x-www-form-urlencoded,
multipart/form-data
, or
text/plain
βfor example, if the POST request sends
an XML payload to the server using application/json,
application/xml
or text/xml
, the
request is preflighted.
Configure Allowed Origin(s)
To configure allowed origins for the Open Commerce API, perform the following steps:
- In Business Manager, select Administration > Site Development > Open Commerce API Settings.
- Select a site for which you want to configure allowed origins.
- In the text field, you configure the property allowed_origins per client application in the JSON document, as described below.
{
"_v" : "23.2",
"clients":
[
{
"allowed_origins":["http://foo.com","https://secure.foo.com:8888"],
"client_id":"[your_own_client_id]",
"resources":
[
{
"resource_id":"/customers/auth",
"methods":["post"],
"read_attributes":"(**)",
"write_attributes":"(**)"
},
{
"resource_id":"/baskets",
"methods":["post"],
"read_attributes":"(**)",
"write_attributes":"(**)"
},
...
]
}
]
}
The '*' wildcard is not supported.
Examples
Example 1: GET
request with unknown origin - no
Access-Control-Allow
headers in response; browser
should reject the response by forcing same origin policy.
REQUEST:
GET /dw/shop/v23_2/products/123/availability HTTP/1.1
Host: example.com
Origin: http://bar.com
RESPONSE:
HTTP/1.1 200 OK
Content-Length: 67
Content-Type: application/json; charset=UTF-8
Cache-Control: max-age=60,must-revalidate
{
"id":"123",
"name":"Shirt",
"orderable":true
}
Example 2: GET request with known origin -
Access-Control-Allow
headers in response; modern
browsers should make the response content available.
REQUEST:
GET /dw/shop/v23_2/products/123/availability HTTP/1.1
Host: example.com
Origin: http://foo.com
RESPONSE:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://foo.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: location,x-dw-version-status
Content-Length: 67
Content-Type: application/json; charset=UTF-8
Cache-Control: max-age=60,must-revalidate
{
"id":"123",
"name":"Shirt",
"orderable":true
}
Example 3: POST request with unknown origin:
Pre-flight OPTIONS request contains no confirming
Access-Control-Allow
headers; browsers skip the
second request.
REQUEST:
OPTIONS /dw/shop/v23_2/baskets HTTP/1.1
Host: example.com
Origin: http://bar.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type
RESPONSE:
HTTP/1.1 204 No Content
Allow: POST
Example 4: POST request with known origin:
Pre-flight OPTIONS request has confirming
Access-Control-Allow
headers in response; browsers
execute the second request.
REQUEST 1:
OPTIONS /dw/shop/v23_2/baskets HTTP/1.1
Host: example.com
Origin: http://foo.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type
RESPONSE 1:
HTTP/1.1 204 No Content
Access-Control-Allow-Methods: POST
Access-Control-Max-Age: 86400
Access-Control-Allow-Origin: http://foo.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Content-Type
Allow: POST
REQUEST 2:
POST /dw/shop/v23_2/baskets HTTP/1.1
Host: example.com
Origin: http://foo.com
Authorization:Bearer eyJfdiI6IjXXXXXX.eyJfdiI6IjEiLCJleHAXXXXXXX.-d5wQW4c4O4wt-Zkl7_fiEiALW1XXXX
Content-Type: application/json
Content-Length: 67
{
"product_id" : "456",
"quantity" : 1.00
}
RESPONSE 2:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://foo.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: location,x-dw-version-status
Content-Type: application/json;charset=UTF-8
Cache-Control: max-age=0,no-cache,no-store,must-revalidate
Content-Length: 158
{
"_v" : "23.2",
"_resource_state" : "ba4e84383e1790597e49eeee34b201633d80ed3f499992f5af11d639dd903a36"
"currency" : "USD",
"product_sub_total" : 40.00,
"product_total" : 40.00,
"shipping_total" : null,
"tax_total" : null,
"order_total" : null,
"product_items" :
[
{
"product_id" : "456",
"item_text" : "Product foo",
"quantity" : 1.00,
"product_name" : "foo",
"base_price" : 40.00,
"price" : 40.00
}
]
}