1

Hi im implementing an SSO client using node-oidc-provider

Background:

node-oidc-provider has a built-in form submission that requires the user to "confirm that he wants to sign out" by clicking a button that submits a hidden form that will revoke his OAuth token.

I would like to skip that confirmation step by self-submitting the form on page load, like the package author suggests here

The problem:

I've added a nonce to the script and meta tag but the browsers still refuse to load my script

async function getNonce () {
  const crypto = require("crypto");
  return crypto.randomBytes(16).toString("base64");
}

async function logoutSource (ctx, form) {
  // @param ctx - koa request context

 const nonce = await getNonce();

 ctx.body = `<!DOCTYPE HTML>
   <head>
     <title>Logout</title>
     <meta http-equiv="content-security-policy"
      content="
        script-src 'nonce-${nonce}' strict-dynamic 'unsafe-inline';
        default-src 'self';
     ">
   </head>
   <body>
     ${form}
     <script nonce="${nonce}">
       var form = document.forms[0];
       var input = document.createElement('input');
       input.type = 'hidden';
       input.name = 'logout';
       input.value = 'yes';

       form.appendChild(input);
       form.submit();
     </script>
   </body>
 </html>`;

Looking at the request in the browsers network tab I see the nonce enter image description here

However when the browser renders the response the nonce is stripped away citing a CSP violation, Im guessing there is something wrong with the meta head but after reading the CSP docs I have been unable to figure out the error

Update 1 Chrome shows this error message enter image description here

Firefox: Content Security Policy: The page’s settings blocked the loading of a resource at inline (“script-src”).

Matti
  • 495
  • 6
  • 21
  • 1
    The `'strict-dynamic'` should be single quoted. Modern browsers hide the value of `'nonce'` from tag to avoid nonce exfiltration and reuse. And you didn't show a CSP violation message, whicj can be helpful to figure out what cause an error. – granty Sep 30 '21 at 18:02
  • Thanks, I have added the missing quotes and ill update the post with the error message, it just felt so generic that I didn't even consider adding it here – Matti Oct 01 '21 at 06:50
  • The `inline script` can be either ` – granty Oct 01 '21 at 20:35
  • Ah I didn't know about `report-sample` been wondering why there wasn't a clearer error message as the browser knows exactly why it rejected to run my script! Line 13 you can see in the network tab image above, its the opening of my script tag – Matti Oct 03 '21 at 12:08
  • I guess the error message is intentionally left generic – Matti Oct 03 '21 at 12:43
  • After carefully examining facts in your question, looks like I found the answer, pls see it below. – granty Oct 03 '21 at 14:16

1 Answers1

1

Looks like you have published two CSPs at the same time - first one ia HTTP header and second one via meta tag.
In this case all sources should pass both CSPs unscratched to be allowed, but the first CSP doesn't have a nonce.
Presumably the first CSP is default CSP been published by Helmet middleware, which is in the dependencies of NodeJS.

Check the HTTP response header, the manual is here.

If Content-Security-Policy HTTP header is present, you have 2 opts:

  • to add nonce into HTTP header and remove meta tag CSP.
  • to disable CSP in HTTP header and use the meta tag.

If this is the tricks of Helmet then CSP can be turned off using:

// This disables the `contentSecurityPolicy` middleware but keeps the rest.
app.use(
  helmet({
    contentSecurityPolicy: false,
  })
);
granty
  • 7,234
  • 1
  • 14
  • 21