UPDATE 27/4/2022 : CSP is greatly enhanced in the upcoming 10.0.4 release, so doing this yourself will no longer be necessary.

I was trying to implement CSP in ISAM, specifically to add nonce protection for my client-side javascript code.

This is specifically for Infomap authentication policies.

The mechanism is as follows :

  • add a header that includes a nonce (a random value that is different for every page)
  • add the (hash) nonce to the script tags

Nonce

I implemented this by generating a random value in the mapping rule for the infomap. I choose a 13 characters random string for no particular reason. Ideally, you’d make sure the nonce is unique and you would also verify it’s unique (server-side).

// generate a nonce  
var templateNonce = OAuthMappingExtUtils.generateRandomString(13);  
macros.put("**@TEMPLATENONCE@**", templateNonce);  

Then , in the html page for the Infomap, I add a header:

<% templateContext.response.setHeader("Content-Security-Policy","default-src 'self'; script-src 'nonce-"+templateContext.macros["@TEMPLATENONCE@"]+"';"); %>

Every script tag then needs to include a nonce.

<script type="text/javascript" nonce="@TEMPLATENONCE@"/>

Hash

To accommodate the piece of code that’s added by WebSEAL for the IV_JCT cookie, you can generate a sha256 hash value. You need to generate a hash by taking all the text between the ‘script’ tags - including all carriage returns, spaces, tabs and whatnot. I paste that text into a text file, and then use openssl to generate the hashes.

<SCRIPT type="text/javascript">  
document.cookie = "IV_JCT=%2Fmga; path=/; secure";
</SCRIPT>

The hash value for the piece of javascript code is the same for everyone using ISAM, so you could add it to your WebSeal /mga junction (that is created using -j).

To generate it, you need to copy all the code (including comments, whitespace, tabs, carriage returns and what else) , put it in a file and generate the hash:

cat test.js | openssl sha256 -binary | openssl base64

The result is always the same:

1ICPqU0KcyH0XeAruG+H5+h7JCqchnCGp1SD7g5JON8=

Precede it with “sha256-“ and add to the header:

<%  
templateContext.response.setHeader("Content-Security-Policy","default-src
      'self'; script-src 'nonce-"+templateContext.macros   ["@TEMPLATENONCE@"]+"' 'sha256-1ICPqU0KcyH0XeAruG+H5+h7JCqchnCGp1SD7g5JON8=';");
%>

NOTE The wizards create the /mga junction with the javascript cookie option. That is not CSP compliant (inline). Setting the Junction Cookie generation to httpheader avoids all of that.
In that case, the cookie is planted on the browser using html (not javascript), thus avoiding the CSP problems. It should not be necessary anyway to have a junction cookie for the /mga junction !