Maximo and CORS

March 1, 2022

Introduction

For anyone who has ever encountered the Access to XMLHttpRequest at 'http://my-maximo.com' from origin at 'http://my-web-app.com' has been blocked by CORS policy: Response preflight request doesn't pass access control check error, this post is for you.

This error is the result of the Same-Origin security Policy (SOP), which by default prevents a script request from one origin from accessing resources in another origin. In the example error message, http://my-web-app.com is one origin and has a script attempting to access http://my-maximo.com, a second origin.

The SOP policy is designed to prevent malicious scripts from one origin accessing information on another origin through the document object model (DOM). This only applies to scripts, and not other resources such as images, css or other resources.

For an excellent overview and reference on CORS, see the Mozilla Developer Network (MDN) entry here: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

With later versions of Maximo providing a rich REST API, the opportunity to access and consume Maximo data from external web applications becomes possible, but quickly runs into challenges with the same-origin policy if the external application is hosted outside the Maximo host. Fortunately there is a Cross-Origin Resource Sharing (CORS) policy, which allows a server to allow other origins to access otherwise secured resources.

This only applies to browser based applications accessing the Maximo REST API, so for many, this will never apply. However, for those who run into Same-Origin and CORS errors, the following will provide a guide to properly configure your Maximo environment for access from external web applications.

Configuring CORS Policies

As previously mentioned, CORS policies allows a server (in our case Maximo), to specify other origins that are allowed to load resources from it. This includes the details of the resources that can be accessed, and the HTTP mechanisms that allowed to be used as part of this access.

As CORS policies are defined in the HTTP response headers, there are multiple approaches for configuring a Maximo environment to return the desired CORS headers. In this post we are going to cover three different approaches: one for the traditional IBM HTTP Server (IHS) with WebSphere Traditional, one for WebSphere Liberty Profile (WLP) and one native to Maximo.

CORS Headers

The table below lists the CORS-related HTTP headers with a description of how they impact behavior.

HeaderDescription
Access-Control-Allow-CredentialsThe only valid value is true (case sensitive) and indicates that credentials such as authorization headers may be shared.
Access-Control-Allow-OriginThe origin allowed by the server. This may contain the * wildcard character.
Access-Control-Allow-MethodsThe HTTP methods allowed: DELETE, GET, OPTIONS, PATCH, POST, PUT. Note that Maximo does not support PATCH.
Access-Control-Allow-HeadersThe HTTP headers allowed in a CORS request. This may include common headers such as Content-Type.
Access-Control-Expose-HeadersThe HTTP response headers that are available to the external origin script.
Access-Control-Max-AgeThe maximum age in seconds of the initial preflight CORS access check prior to the request being made.

Note that for the Access-Control-Allow-Origin header additional security protocol restrictions apply, such that a http protocol origin cannot access a https resource.

Per our example, to allow our external web application at https://my-web-app.com to have general access to the Maximo REST API, we want to configure our Maximo environment to return the following headers:

HeaderValue
Access-Control-Allow-Credentialstrue
Access-Control-Allow-Originhttps://my-web-app.com
Access-Control-Allow-MethodsPOST, GET, HEAD, PUT, OPTIONS
Access-Control-Allow-Headersauthorization, content-type, maxauth, x-public-uri
Access-Control-Expose-Headerscsrftoken
Access-Control-Max-Age3600

IBM HTTP Server

The IBM HTTP Server (IHS) is the standard web server for accessing Maximo that is deployed in the WebSphere Application Server (WAS) Traditional application server. If you see this login screen when you deploy your Maximo EAR file, you are using WebSphere Traditional.

WebSphere Login

The IHS is a branch of the Apache Web Server and long predates CORS, so there is no specific support for specifying CORS policies. Fortunately there is the mod_headers module that allows headers to be dynamically injected by the server and this module is provided by default with the IHS.

Full documentation for the mod_headers can be found here https://httpd.apache.org/docs/current/mod/mod_headers.html

To add mod_headers support simply use the LoadModule directive with the name of the module and path to the .so (Linux) or .dll (Windows) library. This will load the Header directive which can then be used with the set action to add headers to each response. The following example can be added to the $IHS_ROOT/conf/httpd.conf file where $IHS_ROOT is the installation folder for IHS.

LoadModule headers_module modules/mod_headers.so
Header set Access-Control-Allow-Credentials true
Header set Access-Control-Allow-Origin https://my-web-app.com
Header set Access-Control-Allow-Methods "POST, GET, HEAD, PUT, OPTIONS"
Header set Access-Control-Allow-Headers "authorization, content-type, maxauth, x-public-uri"
Header set Access-Control-Expose-Headers "csrftoken"
Header set Access-Control-Max-Age 3600

I personally prefer to keep customizations and configurations to IHS in a separate file. I create a directory named maximo in the $IHS_ROOT/conf directory and then add the Include directive Include conf/maximo/*.conf at at the end of the $IHS_ROOT/conf/httpd.conf file. I then place each configuration in its own .conf file and they are dynamically included in the configuration, so I can easily identify, modify or remove configurations. For this example I would create a file named $IHS_HOME/conf/maximo/headers.conf and place the above configuration in it.

SameSite Set-Cookie Attribute

Although not specifically CORS, the SameSite Set-Cookie attribute specifies when cookies will be sent to cross site domains. If you require cookies to be shared with cross site domains you must specify the SameSite Set-Cookie attribute as None. This used to be the default value, but it has recently changed to default to Lax, which only sends cookies when the user is navigating to the origin site. Full details of the SameSite Set-Cookie attribute can be found here https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite.

Fortunately, IBM has provided a configuration file to allow the appropriate header response. Following the previous advice, you can download the same-site-global.conf file from IBM and save it in the $IHS_HOME/conf/maximo/ directory.

http://publib.boulder.ibm.com/httpserv/ihsdiag/_static/samesite-global.conf

A support article from IBM is available here to understand how SameSite is handled by WebSphere and IHS. https://www.ibm.com/support/pages/browser-changes-samesite-cookie-handling-and-websphere-application-server

WebSphere Liberty Profile

WebSphere Liberty Profile (WLP) is the new light weight version of WebSphere that includes composable features so you only need to load what is needed and not what is not. It became available for use in Maximo 7.6.0.9 and is the default (and only choice) for Maximo Application Suite.

WLP has built in CORS support that can be configured as part of the deployment server.xml configuration. The configuration is very simple, add the <cors /> XML tag with the following attributes that correspond the the CORS headers. The previous example for IHS is re-implemented below.

<cors domain="maximo/oslc"
allowCredentials="true"
allowedOrigins="https://my-web-app.com"
allowedMethods="POST, GET, HEAD, PUT, OPTIONS"
allowedHeaders="authorization, content-type, maxauth, x-public-uri"
exposeHeaders="csrftoken"
maxAge="3600" />

SameSite Set-Cookie Attribute

WebSphere Liberty provides the <samesite /> XML tag that supports the lax, strict and none attributes with each containing a comma separated list of cookie names for each policy or the wildcard character * to indicate all cookies. The <samesite /> XML tag can be embedded within the <httpEndpoint /> tag or standalone with an id attribute that can be referenced through the samesiteRef attribute on the <httpEndpoint /> tag. An example of the configuration can be seen below.

<httpEndpoint id="defaultHttpEndpoint"
httpPort="80"
httpsPort="443" >
<samesite lax="firstCookie,secondCookie" strict="strictCookie" none="all, other, cookies"/>
</httpEndpoint>

A full discussion of the ` XML tag can be found on the Open Liberty blog below.

https://openliberty.io/blog/2020/03/25/set-samesite-attribute-cookies-liberty.html

Maximo

The previous examples not withstanding, Maximo provides CORS support directly without having to modify the application server configuration. The CORS headers can be added simply by setting the following Maximo System Properties. The table below provides the property name, description and the corresponding CORS header that it affects.

PropertyDescriptionAffected Header
mxe.oslc.aclalloworiginCORS http origin urls allowed.Access-Control-Allow-Origin
mxe.oslc.aclallowmethodsCORS http methods allowed.Access-Control-Allow-Methods
mxe.oslc.aclallowheadersCORS http headers allowed.Access-Control-Allow-Headers
mxe.oslc.aclexposeheadersCORS http response headers allowed.Access-Control-Expose-Headers

All you have to do is set these properties with the values previously discussed and your CORS headers will be properly set.

SameSite Set-Cookie Attribute

Maximo does not currently have support for setting the SameSite Set-Cookie attribute directly. If you need to modify the SameSite attribute of the Set-Cookie header you will need to apply it either in Apache or WebSever Liberty as discussed previous.

Conclusion

In this post we explored configuring the IBM HTTP Server, WebSphere Liberty Profile, and Maximo directly for Cross-Origin Resource Sharing. While the Maximo approach is by far the easiest and straight forward configuration, the other options are sometimes useful tools and are good for understanding how CORS works. As mentioned at the start of the post, CORS only affects applications running in a browser, so third party application, mobile solutions, and other utilities are not impacted by CORS.

If you have any questions or comments please reach out to us at [email protected]

In the time it took you to read this blog post...

You could have deployed Opqo, our game-changing mobile solution for Maximo.

Opqo is simple to acquire, simple to deploy and simple to use, with clear transparent monthly pricing that is flexible to your usage.