Skip to main content

Overview

A Content Security Policy (CSP) is a security standard that helps prevent cross-site scripting (XSS), clickjacking, and other code injection attacks. It works by telling the browser exactly which sources of content are trusted. Dynamic’s SDK injects inline <style> elements to render its authentication widgets, including styles within Shadow DOM containers. By default, a strict CSP that disallows inline styles (style-src 'self') will block these styles and break the widget’s appearance. The cspNonce setting solves this by letting you pass a server-generated nonce to the SDK. Dynamic applies that nonce to every inline <style> and <link> tag it creates, so they pass your CSP without requiring 'unsafe-inline'.

How it works

  1. Your server generates a unique, unpredictable nonce for each page request
  2. Your server includes the nonce in both the CSP header and passes it to your application
  3. You pass the nonce to DynamicContextProvider via settings.cspNonce
  4. The SDK automatically applies the nonce to all inline styles it injects, including:
    • Shadow DOM reset and widget styles
    • Theme styles (<style> and <link> tags in <head>)
    • CSS overrides
    • Legacy browser compatibility styles
The browser then allows <style> tags with the matching nonce and blocks everything else, keeping your strict CSP intact.

Setup

1

Generate a nonce on your server

Create a unique, unpredictable nonce for every page request. Use a cryptographically secure random value — never hardcode or reuse a nonce.
middleware.ts
Then read the nonce in your layout:
app/layout.tsx
2

Set the CSP header

Include the nonce in your style-src or style-src-elem directive. If you use embedded wallets, also include frame-src for the iframe connection.
For static sites where you cannot set HTTP headers, you can use a meta tag. Note that this is less secure than a server-set header because the nonce is visible in the HTML source.
Vercel does not support dynamic nonces in vercel.json headers. Use Next.js middleware (shown above) or a Vercel Edge Function to generate nonces per request.
If you’re already setting CSP headers, append the nonce to your existing style-src and style-src-elem directives rather than replacing them.
3

Pass the nonce to DynamicContextProvider

Pass the nonce string as cspNonce in your provider settings. The SDK will apply it to every inline <style> and <link> element it creates.

Full example: Express + React

Here is a complete example showing nonce generation, CSP header configuration, and SDK integration. Server (Express):
server.js
Client (React):
App.tsx

CSP directives reference

Here is a recommended baseline CSP for applications using Dynamic:
The style-src-elem directive (CSP Level 3) provides granular control over <style> elements separately from inline style="" attributes. If your browser support requires it, use style-src instead — it covers both. When a nonce is present in style-src, browsers that support CSP Level 2+ will ignore 'unsafe-inline' for <style> elements, requiring the nonce.

Approaches to avoid

Verifying your setup

You can verify that the nonce is correctly applied by inspecting Dynamic’s style elements in your browser’s DevTools:
  1. Open DevTools > Elements
  2. Find a .dynamic-shadow-dom element and expand its shadow root
  3. Inspect the <style> tags inside — each should have a nonce attribute matching your CSP
You can also check the Console for CSP violation errors. If the nonce is correctly configured, you should see no style-src-elem violations from Dynamic’s styles.

Troubleshooting

Make sure the nonce value passed to cspNonce exactly matches the nonce in your CSP header. The CSP header format is 'nonce-{value}' while the cspNonce prop expects just the value (without the nonce- prefix or quotes).
Other libraries in your application (wallet connectors, toast libraries, etc.) may also inject inline styles without nonce support. These violations are not caused by Dynamic. Check if those libraries offer their own nonce or CSP configuration options.
Dev servers like Vite inject CSS via inline <style> tags for hot module replacement (HMR). These won’t have your nonce and will trigger CSP violations. This is expected in development — in production builds, CSS is bundled into external files that load via <link> tags (allowed by 'self').
If you’re using embedded wallets, make sure your CSP includes frame-src 'self' https://app.dynamicauth.com. See the embedded wallet setup guide for details.
Last modified on March 2, 2026