content-security-policy with nonce in ISAM/ISVA for junction cookie
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=';");
%>