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
- Your server generates a unique, unpredictable nonce for each page request
- Your server includes the nonce in both the CSP header and passes it to your application
- You pass the nonce to
DynamicContextProviderviasettings.cspNonce - 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
<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.
Then read the nonce in your layout:
Node.js / Express
Node.js / Express
Next.js (Middleware)
Next.js (Middleware)
middleware.ts
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.Express.js
Express.js
HTML meta tag (static sites)
HTML meta tag (static sites)
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.
NGINX
NGINX
Vercel (vercel.json)
Vercel (vercel.json)
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.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
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:- Open DevTools > Elements
- Find a
.dynamic-shadow-domelement and expand its shadow root - Inspect the
<style>tags inside — each should have anonceattribute matching your CSP
style-src-elem violations from Dynamic’s styles.
Troubleshooting
Styles are broken but no CSP violations in console
Styles are broken but no CSP violations in console
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).CSP violations from third-party libraries
CSP violations from third-party libraries
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.
Nonce not applied in development (Vite / webpack-dev-server)
Nonce not applied in development (Vite / webpack-dev-server)
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').Embedded wallet iframe blocked
Embedded wallet iframe blocked
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.