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 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 all your WebSeal junctions (if they use -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=';");
%>