How to set up the Content Security Policy header with Phoenix LiveView and support inline styles and scripts with CSP nonces.
I appreciate you adding tests in your examples. Great explanation as well. Thanks
Interesting post, ty.
Follow-up question one year later My understanding is that the nonce stays the same within the same live session. This means that if a few routes share the same live session, navigating between those routes won’t update the nonce. Is my understanding correct?
The idea is that a new nonce is created at every page re-load, but an SPA does load the page only once, then updates parts of it: I think that is the reason why on SPA the use of nonce is discouraged.
I wonder how that reasoning applies to Phoenix: navigating between routes that share the same live session is basically the same of an SPA, but then navigating to a route that creates a new live session would reload the page, which is the wanted behaviour for nonce support, so a Phoenix app is a bit of a “hybrid”.
Is it safe to use nonce with Phoenix? Or should it be avoided? Thoughts? The nonce is very handy so to have it in place would be interesting, as far as it is safe.
Yes, the nonce stays the same for as long as the LiveView process stays alive.
I’ve been using this in production with LiveView ever since writing this post. As long as you use the same nonce as set in the header of the initial page load you’ll be fine.
It gets tricky when you have JS libraries inject script or style tags all over the place. Many JS libraries don’t have any ability to propagate the nonce, so out of necessity I end up just listening to any style or script tags that is added to the page and inject the nonce attribute on them. Not really safe, but there’s not much else that can be done, and it’s better than nothing.
If you don’t deal with that problem then this is very safe. The LiveView session controls everything rendered and knows the nonce.
If you can you should just push all your JS and CSS to your static asset files. If absolutely necessary with inline scripts/styles, opt for using content hash in the header. Nonce is what you reach for last, when you got tags with too many content permutations to do it any other way.