iFrames and IBM BAW 20

Photo by pine watt / Unsplash

One of our clients upgraded to IBM BAW 20 last week and had issues with a custom app. The app communicates with BAW using iframes. In some cases, the app embeds a BAW human service exposed as a url in an iframe. In other cases, a coach in BAW embeds the app in an iframe.

After upgrading to BAW 20.0.0.2, users started getting the following errors: Refused to frame 'https://my-sample.app/' because an ancestor violates the following Content Security Policy directive: "frame-ancestors 'self'".

Let us see why this happened after upgrade.

X-Frame-Options Deprecated

While the X-Frame-Options header is supported by the major browsers, it was never standardized. The Content-Security-Policy HTTP header has a frame-ancestors directive which obsoletes this header for supporting browsers. So, the new updates to BAW now includes CSP which overrides the deprecated x-frame-options.

IBM BAW's out-of-the-box Content Security Policy (CSP)

IBM BAW 20 includes hardened security settings by default. You can read about them here.
In order to view them, you can connect to wsadmin

cd <BAW_root>/profiles/<Dmgr_Profile>/bin
wsadmin -conntype none -lang jython

List the current config

wsadmin> AdminTask.getBPMProperty(['-de', 'WorkflowCenter', '-name', 'Security.ContentSecurityPolicyHeaderValue'])

Should look like this

Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https:; font-src 'self' fonts.gstatic.com data:; worker-src 'self' blob:; child-src 'self' blob:;

What does this mean?
The above CSP has default-src set to 'self' and since there are no frame-src/frame-ancestors directive defined, only the URL with origin from where the web page is served is allowed by the browser in iframes.

In order to allow content from BAW into the iframes of the custom app, let us look at some key directives in detail.

default-src Directive

default-src directive serves as a fallback for the other CSP fetch directives. Fetch directives control the locations from which certain resource types may be loaded.

frame-src Directive

frame-src directive specifies valid sources for nested browsing contexts loading using elements such as <frame> and <iframe>. If this directive is absent, the browser will look for the child-src directive, which falls back to the default-src directive.

Note: Chrome 59 and higher skips the child-src directive.

In our case, we need the frame-src to load anything which comes from secure sites. So, we set this as frame-src 'self' https:

frame-ancestors Directive

frame-ancestors directive specifies valid parents that may embed a page using <frame>, <iframe>, <object>, <embed>, or <applet>.

Tip: Setting this directive to 'none' is similar to X-Frame-Options: deny (which is also supported in older browsers).

In our case, we need the frame-ancestors to allow the sample app url. So, we set this as frame-ancestors 'self' https://my-sample.app

Putting all together need our CSP header to look like

Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https:; font-src 'self' fonts.gstatic.com data:; worker-src 'self' blob:; child-src 'self' blob:; frame-src 'self' https:; frame-ancestors 'self' https://my-sample.app;

How to configure CSP in BAW?

Back in your command prompt/shell, connect to wsadmin scripting client. Use the setBPMProperty command to set the value of an Business Automation Workflow custom property, Security.ContentSecurityPolicyHeaderValue , in the configuration repository.

wsadmin> AdminTask.setBPMProperty(['-de', 'WorkflowCenter', '-name', 'Security.ContentSecurityPolicyHeaderValue', '-value', "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https:; font-src 'self' fonts.gstatic.com data:; worker-src 'self' blob:; child-src 'self' blob:; frame-src 'self' https:; frame-ancestors 'self' https://my-sample.app;"])

wsadmin> AdminConfig.save()

You can confirm that the value is set properly by using the getBPMProperty command.

wsadmin> AdminTask.getBPMProperty(['-de', 'WorkflowCenter', '-name', 'Security.ContentSecurityPolicyHeaderValue'])

In WAS network deployment (ND) environments, the value of the custom property is set when the next node synchronization occurs. You need to restart the server or cluster after running the command.

Not done yet

Once the restart is done, in Chrome browser version 80+, you will start seeing the BAW login screen and the  Uncaught DOMException: Blocked a frame with origin "https://my-sample.app" from accessing a cross-origin frame. error in your browser console. The error in the console is misleading and it is just a side-effect of the BAW not able to set its session cookies in Chrome, hence the app is redirecting to the login screen.

SameSite attribute

Chrome as a part of its secure-by-default model for handling cookies, Google Chrome will stop sending third-party cookies in cross-site requests unless the cookies are secured and flagged using an IETF standard called SameSite. With the SameSite attribute, website developers have the power to set rules around how cookies are shared and accessed. The SameSite attribute can be set with the following values:
Strict: Restricts cross-site sharing altogether.
Lax: All the sites belonging to the same domain can set and access cookies.
None: Allows third-party cookies to track users across sites. If you just specify None without Secure the cookie will be rejected. Secure ensures that the browser request is sent by a secure (HTTPS) connection.

Setting SameSite attribute in IBM BAW

IBM BAW and Websphere by default does set the session cookies secure, but they do not set the SameSite attribute. As part of APAR PH22157, we have the ability to set this attribute. Since we need it to work cross site, we need to set SameSite attribute to None

Here are the steps to set this on the BAW application cluster's server.

In the administrative console, navigate to the following panel to add these HTTP Channel properties:

  1. Navigate to WebSphere application servers > server_name.
  2. Under Web Container Settings, click Web container transport chains > chain_name > HTTP inbound channel > Custom properties
  3. Click New button to add a new property with the following
    Name    –             sameSiteNone
    Value     –             *
  4. Click OK
  5. Save changes
  6. Restart the servers.

Now that we have fixed all the issues, the cross site BAW iframe should work as expected.

References

Content-Security-Policy - HTTP | MDN
The HTTP Content-Security-Policy response header allows web site administrators to control resources the user agent is allowed to load for a given page. With a few exceptions, policies mostly involve specifying server origins and script endpoints. This helps guard against cross-site scripting …
Chrome’s Changes Could Break Your App: Prepare for SameSite Cookie Updates
SameSite changes coming to Chrome that affect how third-party cookies are handled & how to test to see if your site is impacted and how to fix it.
IBM Knowledge Center
setBPMProperty documentation
IBM Knowledge Center
HTTP transport channel custom properties documentation
IBM Knowledge Center
Security-hardening properties - Hardening IBM Business Automation Workflow
David Knapp

David Knapp