Content Management and Capture

Content Management and Capture

Come for answers. Stay for best practices. All we’re missing is you.

 View Only

Cross-Origin Resource Sharing (CORS) configuration for IBM Content Services GraphQL (CS-GraphQL)

By SRIDHAR Satuloori posted Fri November 12, 2021 06:54 PM

  
Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any origin (domain, scheme, or port) other than its own from which a browser should permit loading resources.  This post is to help developers, deployers, and administrators to understand the basic concepts of CORS and CORS configuration required for the Content services GraphQL. 
CORS is a powerful feature that blocks malicious JavaScript calling unauthorized resources from a different domain than the origin.  By default, the browsers CORS implementation blocks requests  from 

  • A domain other than the origin domain ( ex: the origin page at ibm.com calls csGraphql.com, note the use of different domains)
  • A subdomain other than the origin subdomain (ex: the origin page at myapp.ibm.com calls csgraphql.ibm.com, note the use of  different subdomains)
  • A port other than the origin port (ex: the origin page from myapp.ibm.com:80 calls myapp.ibm.com:9080, ports are different) 
  • A scheme other than the non-origin scheme (ex the origin page loaded with https://myapp.ibm.com calls the page to be loaded with http:/myapp.ibm.com. protocols are different). 
Content Services GraphQL API provides a schema and an easy-to-understand GraphQL query language system that simplifies application development for your Content Platform Engine.  This API works using the HTTP or HTTPS protocol. Typically an application that is loaded from a different domain uses the GraphQL API directly from the client browser.  To enable these cross-origin requests, you must configure the server so that the CORS is enabled for the URL's , methods, credentials, and headers that are used in the application.
Example:
A user accesses an application from "domain A", which requires the browser to issue a call to the CS-GraphQL system using JavaScript. For the browser, the request/response from the CS-GraphQL system is not the origin, and unless the CS-GraphQL system explicitly allows the cross-origin data, the browser's CORS implementation blocks the response.
For the CP4BA containers in which the CS-GraphQL is deployed on an IBM WebSphere Liberty profile application server, the required CORS information can be added in two ways

Option 1
Add the CORS configuration to the server.xml file that defines the server configuration. the following example Illustrates the XML to add to the server.xml file

<cors domain="/content-services-graphql"
        allowedOrigins="https://*.ibm.com,https://demo.myapp.ibm.com"
        allowedMethods="GET, POST, OPTIONS"
        allowedHeaders="Connection,Pragma,Cache-Control,ECM-CS-XSRF-Token,XSRFtoken,Origin,User-Agent,Content-Type,Content-Length,Accept-Control-Request-Method,Accept-Control-Request-Headers,Accept,Referer,Accept-Encoding,Accept-Language,DNT,Host,Content-Length,Cache-control,Cookie,Authorization,Access-Control-Allow-Origin"
        exposeHeaders="Content-Disposition,Content-Length,ECM-CS-XSRF-Token,Content_Type,Content-Language,X-Powered-By,Date,Allow,Transfer-Encoding,$WSEP,DNT,Access-Control-Allow-Credentials,Access-Control-Allow-Headers,Access-Control-Allow-Max-Age,Access-Control-Allow-Methods,Access-Control-Allow-Origin,Access-Control-Expose-Headers,Connection,Cache-control,Cookie,x-content-download"
        allowCredentials="true"
        maxAge="3600" />

Option 2:
Create a separate cors.xml wile with the following snippet, put the file in the configDropins/override folder

<?xml version='1.0' encoding='UTF-8'?>
<server>
<cors domain="/content-services-graphql"
       allowedOrigins="https://*.ibm.com,https://demo.myapp.ibm.com"
        allowedMethods="GET, POST, OPTIONS"
        allowedHeaders="Connection,Pragma,Cache-Control,ECM-CS-XSRF-Token,XSRFtoken,Origin,User-Agent,Content-Type,Content-Length,Accept-Control-Request-Method,Accept-Control-Request-Headers,Accept,Referer,Accept-Encoding,Accept-Language,DNT,Host,Content-Length,Cache-control,Cookie,Authorization"
        exposeHeaders="Content-Disposition,Content-Length,ECM-CS-XSRF-Token,Content_Type,Content-Language,X-Powered-By,Date,Allow,Transfer-Encoding,$WSEP,DNT,Access-Control-Allow-Credentials,Access-Control-Allow-Headers,Access-Control-Allow-Max-Age,Access-Control-Allow-Methods,Access-Control-Allow-Origin,Access-Control-Expose-Headers,Connection,Cache-control,Cookie,x-content-download"
        allowCredentials="true"
        maxAge="3600" />
</server>

With either options, the CORS XML contains the following information
  • domain -  Defines the context root for the CS-GraphQL application. For the CORS configuration to be effective, the value provided for the domain must match the incoming request.
  • allowedOrigins - Provides a comma separated list of domains,  The domain specified in HTTP origin header on the request, must be an exact match for one of the domains in the allowedOrigins list.  To allow all incoming domains use an asterisk (*) . To prevent calls from any origins specify "null" as the allowedOrigins.
  • allowedMethods - Provides a list of HTTP methods to which the resource is exposed. For example GET, POST, DELETE, PUT, OPTIONS (OPTIONS header is needed for CPRS preflight requests)
  • allowedHeaders - Provides a comma-separated list of HTTP headers from request that the Liberty server can read from, Use an asterisk (*) to allow all headers,
  • exposeHeaders  - Provides a comma-separated list of HTTP headers that can be read by the application in the browser.
  • allowCredentials - If set to true,  allows the requests to contain the credentials, in other words, the server reads the credentials sent by the request.
Troubleshooting
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://csgraphql.ibm.com/content-services-graphql/graphql'. (Reason: CORS header 'Access-Control-Allow-Origin' missing).
Access to XMLHttpRequest at 'https://csgraphql.ibm.com/content-services-graphql/graphql' from origin 'https://myapp.ibm.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Access to fetch at 'http://gcsgraphql.ibm.com:9082/content-services-graphql/graphql' from origin 'http://myapp.ibm.com:9080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

All the above errors imply that the CORS configuration on the server does not match the request origin. To obtain more details on the cause of the issue on the Liberty server add the following to the liberty server trace specification.

*=info:CorsService=all:GenericBNF=all
To make your application work,  as a test, allow requests from all origins (allowedOrigins="*")  and allow all headers(allowedHeaders="*"),  Setting these options makes the security wide open. Following  is a sample  cors.xml that illustrates these settings 
<?xml version='1.0' encoding='UTF-8'?>
<server>
<cors domain="/content-services-graphql"
        allowedOrigins="*"
        allowedMethods="GET, POST, OPTIONS"
        allowedHeaders="*"
        exposeHeaders="Content-Disposition,Content-Length,ECM-CS-XSRF-Token,Content_Type,Content-Language,X-Powered-By,Date,Allow,Transfer-Encoding,$WSEP,DNT,Access-Control-Allow-Credentials,Access-Control-Allow-Headers,Access-Control-Allow-Max-Age,Access-Control-Allow-Methods,Access-Control-Allow-Origin,Access-Control-Expose-Headers,Connection,Cache-control,Cookie,x-content-download"
        allowCredentials="true"
        maxAge="3600" />
</server>

Once you have verified everything functions correctly, slowly lock down the system to get the proper security.  If for some reason your application is not able to read some of the headers sent by CS-GraphQL, check the exposeHeaders list.
0 comments
42 views

Permalink