Add your Content-Security-Policy either by configuring your server, or with the meta tag.
Remember that a nonce MUST be generated per requests.
Add the nonce to react-dsfr
src/main.tsx
import React from"react";import ReactDOM from"react-dom/client";import { App } from"./App";import { startReactDsfr } from"@codegouvfr/react-dsfr/spa";constnonce="123456789"; // you have to inject it on renderstartReactDsfr({ defaultColorScheme:"system", nonce });ReactDOM.createRoot(document.getElementById("root") asHTMLElement).render( <React.StrictMode> <App /> </React.StrictMode>);
To get the nonce, you have to enable SSR with Vite and either inject the value in process.env or in a additional custom meta tag in your index.html. You can also infer it by using the content of the Content-Security-Policy meta tag if you configured the header this way.
For more information about SSR in Vite see the following page.
First configure the nonce in the <DsfrHead /> tag in your root layout:
app/layout.tsx
import { DsfrHead } from"@codegouvfr/react-dsfr/next-appdir/DsfrHead";import { DsfrProvider } from"@codegouvfr/react-dsfr/next-appdir/DsfrProvider";import { getHtmlAttributes } from"@codegouvfr/react-dsfr/next-appdir/getHtmlAttributes";import { StartDsfr } from"./StartDsfr";import { defaultColorScheme } from"./defaultColorScheme";import Link from"next/link";import { headers } from"next/headers";exportdefaultfunctionRootLayout({ children }: { children:JSX.Element; }) {constnonce=headers().get("x-nonce") ??undefined;//NOTE: The lang parameter is optional and defaults to "fr"constlang="fr";return ( <html {...getHtmlAttributes({ defaultColorScheme, lang })} > <head> <StartDsfr /> <DsfrHeadLink={Link} nonce={nonce} /> </head> <body> <DsfrProviderlang={lang}> {children} </DsfrProvider> </body> </html> );}
The X-Nonce header is forwarded by the middleware.ts as suggested by Next.js.
It important to remember that reading headers in the root layout turns all pages to dynamic rendering opt-in. This is mandatory for nonce.
If you use the NextAppDirEmotionCacheProvider, don't forget to add the nonce to it accordingly to what Emotion and MUI needs: <NextAppDirEmotionCacheProvider options={{ "key": "css", nonce, prepend: true }}>
Then you have to tell react-dsfr to read and forward the nonce injected to all other scripts and styles by adding doCheckNonce: true; to the startReactDsfr() function:
Next.js with old Pages Router is not supported. As per Next.js suggests, we recommended migrating to App Router.
Create React App by itself is a way to build static sites which by definition cannot handle dynamic headers (like CSP) per request as no server will serve the pages.
Before getting into nonce configuration, you have ponder whether or not you need that level of security within your static app, and if so, choosing a solution to generate and inject the nonce into your app.
Once your injected the nonce into your app, add the following code:
import React from'react';import ReactDOM from'react-dom/client';import App from'./App';import { startReactDsfr } from"@codegouvfr/react-dsfr/spa";constnonce="123456789"// have to be dynamic and injectedstartReactDsfr({ defaultColorScheme:"system", nonce });constroot=ReactDOM.createRoot(document.getElementById('root') asHTMLElement);root.render( <React.StrictMode> <App /> </React.StrictMode>);
Your framework isn't supported? Let's get in touch!
Trusted Types Policy
Trusted Types are supported out-of-the box.
When configuring your CSP you only have to add our policy names to your list: