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 toX-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:
- Navigate to WebSphere application servers > server_name.
- Under Web Container Settings, click Web container transport chains > chain_name > HTTP inbound channel > Custom properties
- Click New button to add a new property with the following
Name – sameSiteNone
Value – * - Click OK
- Save changes
- Restart the servers.
Now that we have fixed all the issues, the cross site BAW iframe should work as expected.