Thursday, May 25, 2017

CORS support from WSO2 API Manager 2.0.0

Cross-origin resource sharing (CORS) is a mechanism that allows restricted resources  on a web page to be requested from another domain outside the domain from which the first restricted resource was served.

For example, an HTML page of a web application served from makes an <img src >  request for a different domain as '' to get an image via an API request. 
For security reasons, browsers restrict cross-origin HTTP requests initiated from within scripts as in above example and only allows to make HTTP requests to its own domain. To avoid this limitation modern browsers have been used CORS standard to allow cross domain requests. Modern browsers use CORS in an API container - such as XMLHttpRequest or Fetch - to mitigate risks of cross-origin HTTP requests.Thing to  note is it's not only sufficient that the browsers handle client side of cross-origin sharing,but also the servers from which these resources getting need to handle server side cross-origin sharing. WSO2 API Manager is fully capable of handling cross-origin sharing for its exposed APIs from gateway.This feature was there in WSO2 API Manager from 1 .x version series and in 2.x onwards it has more improved.
Let's first start with understanding more about the CORS protocol.
What's CORS
The CORS protocol consists of a set of headers that indicates whether a response can be shared cross-origin.The CORS specification distinguishes two different requests done from browser.
1. Simple requests- A cross origin request from browser which a HTTP GET,HEAD or POST [with content-type text/plain, application/x-www-form-urlencoded and multipart/form-data.]
2. Preflighted requests- A cross origin request from browser other than above simple request type will do an additional request with HTTP OPTIONS method to check the resource server understand about cross-domain requests.
Note,if you add Authentication header to simple requests,those will become preflighted ones.
With above two types of requests,the client [browser] and the server will exchange a set of specific headers for cross-domain requests as below.
  1. Origin: this header is used by the client to specify which domain the request is executed from. The server uses this to allow/not, the cross-domain request.
  2. Access-Control-Request-Method: with the preflighted requests, the OPTIONS request  from client sends this header to check if the target HTTP method is allowed for cross-domain requests by the server.
  3. Access-Control-Request-Headers: with the preflighted requests, the OPTIONS request sends this header to check if headers are allowed for the target method  of cross-domain requests.
  4. Access-Control-Allow-Credentials: this specifies if credentials are supported for cross-domain requests.
  5. Access-Control-Allow-Methods: the server uses this header to acknowledge client which HTTP verbs are allowed for cross domain request. This is typically included in the response headers from server for preflighted requests.
  6. Access-Control-Allow-Origin: the server uses this header to acknowledge client which domains are authorized for the request.
  7. Access-Control-Allow-Headers: the server uses this header to tell which headers are allowed for therequest. This is typically included in the response headers from server for preflighted requests.

WSO2 API Manager support for CORS

The above requirement mostly came with the web application developers who used WSO2 API Manager deployed API resources in their web applications.Most of the time,since the WSO2 API Manager domain and web application domain is different,when accessing such API resources from browser based web applications,support for CORS specification was identified as an essential feature.
By default,WSO2 API Manager handle setting CORS headers in it's gateway component itself without passing the CORS requests to back-end to handle CORS scenario.
There's a synapse based handler called CORSRequestHandler which will be handle CORS support for each API invocation.
The flow would be as below for default API invocations.

default flow

When an API request comes to APIM gateway ,the defined  CORSHandler in each API will be executed in request and response flow.By default when create APIs from API Publisher,the 'OPTIONS' resource is hidden to defined in API resource section as below.

If an API creator specifically want to handle the CORS preflight call from backend,instead APIM gateway;he can click on 'More' section in design tab as in above image and specifically select the 'OPTIONS' resource as an API resource.Else,if the API creator didn't select the 'OPTIONS' verb as an API resource,the CORS  will be handle by APIM gateway itself;as shows in above image flow.At the request path,CORS handler validate the incoming request method first.If it's an 'options' call,it checks the synapse API xml contains a resource for 'OPTIONS'.If not,the CORS Handler will set the CORS specific headers Access-Control-Allow-Methods,Access-Control-Allow-Headers,Access-Control-Allow-Origin from gateway itself and pass back the response code as 200 with the CORS headers to the client.Then client will initiate the actual cross domain request with specific HTTP method and it'll process as in above image 'default flow'.
If the API creator want to handle CORS from the actual backend,then he can specifically define the 'OPTIONS' verb at API creation time and at the run time flow will be as below.

How WSO2 APIM Gateway set CORS headers
From API Manager 2.0 onwards,API creators can define Access-Control-Allow-xx headers per API from API Publisher or globally from api-manager.xml   config section as in previous releases.
Add CORS headers per API at API creation time
At runtime ,when an API request come to gateway,with CORS support feature of gateway,the Access-Control allow headers will be set with below validations.
  1. Access-Control-Allow-OriginAPI gateway checks if the incoming request contains a header as 'Origin' and if yes,it'll compare that header value with the  'Access-Control-Allow-Origin' value defined in CORS configuration per API/globally in APIM side.If that origin header is defined in APIM side under CORS config section also,then return back that origin header value as Access-Control-Allow-Origin.Else if the request doesn't send an origin header and if in APIM side Access-Control-Allow-Origin is defined as '*',then APIM gateway will return the Access-Control-Allow-Origin header as '*'.
  2. Access-Control-Allow-Methods: APIM gateway checks if the particular API specific CORS config has defined such value or in api-manager.xml  CORS config section this value is defined.If yes,then match with the actual defined API resource methods in that API and return only the matched method names as Access-Control-Allow-Methods response header.
  3. Access-Control-Allow-Headers: APIM gateway will check if the particular API's CORS configuration/globally has defined a value for Access-Control-Allow-Headers,if yes,respond to client with that value as 'Access-Control-Allow-Headers' header.
  4. Access-Control-Allow-CredentialsAPIM gateway will check if the particular API's CORS configuration/globally has defined a value for Access-Control-Allow-Credentials,if yes and if it set as false,gateway will directly respond to client with that value as 'Access-Control-Allow-Credentials' header.If that value set as true in CORS configurations of APIM side,there's a check to see the value of Access-Control-Allow-Origin in gateway side.If it's not '*',then respond to client with 'Access-Control-Allow-Credentials' header as true.Else as false.
Hope,now you'll be have a basic understanding about how CORS works and how WSO2 API Manager supports it. For more info,refer

No comments:

Post a Comment