Cross Site Request Forgery (CSRF)
Introduction
Section titled โIntroductionโNow that we have routing set up, we need a way to secure our application.
We will start by adding cross-site request forgery CSRF protection to our application.
How can we protect against CSRF?
Section titled โHow can we protect against CSRF?โOne way to protect against CSRF attacks is to use a CSRF token.
This is a unique string that is generated for each user session and is sent with each request to the server.
Before processing any request, the server checks that the token is valid and that it matches the userโs session. If it doesnโt, the request is rejected.
Letโs add this now.
Wrapping the application with extra security
Section titled โWrapping the application with extra securityโLuckily, adding CSRF protection to our application is straightforward.
-
Open
app/root.tsx
. -
Add the following import to the top of your
app/root.tsx
file:app/root.tsx import { type LinksFunction } from '@remix-run/node'import Document from '~/components/shared-layout/Document'import { useNonce } from '~/utils/nonce-provider.ts'import rootLinkElements from '~/utils/providers/rootLinkElements'import HeaderWithSearch from './components/organisms/HeaderWithSearch'import FooterMenuRight from './components/organisms/Footer/FooterMenuRight'import ThemeSwitch from './components/shared-layout/ThemeSwitch.tsx'import { loader } from './__root.server.tsx'import { Outlet, useLoaderData } from '@remix-run/react'import useTheme from './hooks/useTheme.tsx'import { AuthenticityTokenProvider } from 'remix-utils/csrf/react' -
We simply need to wrap our application with this
AuthenticityTokenProvider
to ensure that a valid CSRF token is checked for every request across the entire application.This is done by wrapping the JSX returned by the
App
component with theAuthenticityTokenProvider
, then passing acsrfToken
from thedata
object to theAuthenticityTokenProvider
component:app/root.tsx export default function App() {const data = useLoaderData<typeof loader>()const nonce = useNonce()const theme = useTheme()useToast(data.toast)return (<AuthenticityTokenProvider token={data.csrfToken}><Document nonce={nonce} theme={theme}><div className="flex h-screen flex-col justify-between"><HeaderWithSearch /><div className="flex-1"><Outlet /></div><div className="container flex justify-between pb-5"><ThemeSwitch userPreference={data.requestInfo.userPrefs.theme} /></div><FooterMenuRight /></div></Document></AuthenticityTokenProvider>)} -
Save your changes.
-
Before moving on to the next tutorial, make sure you rearrange the imports at the top of the
app/root.tsx
file by using the VS Code keyboard shortcut SHIFT + ALT + O (Windows) or SHIFT + OPT + O (Mac)
Summary
Section titled โSummaryโAlthough not much has changed visually, weโve added a strong security feature to our application that is crucial for you to write about in your assignment.
Next steps
Section titled โNext stepsโIn the next step, we will secure our application against spambots by adding a โhoneypotโ field to our forms.