Cross Site Request Forgery (CSRF)
Cross-Site Request Forgery (CSRF) is an attack that forces an end user to execute unwanted actions on a web application in which they’re currently authenticated. With a little help of social engineering (such as sending a link via email or chat), an attacker may trick the users of a web application into executing actions of the attacker’s choosing. If the victim is a normal user, a successful CSRF attack can force the user to perform state changing requests like transferring funds, changing their email address, and so forth. If the victim is an administrative account, CSRF can compromise the entire web application.
This functionality is based on the great module by Morgan. You can check out the full documentation and reference here
nuxt-csurf
is disabled by default but you can enable it with default configuration like following:
export default defineNuxtConfig({
security: {
csrf: true
}
})
You can directly define per route settings using the csurf
config (which is the underlying package used for CSRF protection in this library. This should be used directly, not in a security
object)
export default {
routeRules: {
'/api/nocsrf': {
csurf: false
}
}
}
Now, you can use the auto-imported composables for handling CRSF:
// Wrapper around `useFetch` that automatically adds CSRF token in headers
const { data, pending, error, refresh } = useCsrfFetch('/api/login', { query: 'value1' })
// Have access to the CSRF token value
const { csrf } = useCsrf()
Apart from just enabling it, you can pass a custom configuration to the underlying nuxt-csurf
module by using the following interface:
interface ModuleOptions {
https?: boolean,
cookie?: CookieSerializeOptions,
cookieKey?: string,
methodsToProtect?: Array<string>, // the request methods we want CSRF protection for
excludedUrls?: Array<string|[string, string]>, // any URLs we want to exclude from CSRF protection
encryptSecret?: string,
encryptAlgorithm?: string
}
interface CookieSerializeOptions {
domain?: string | undefined;
encode?(value: string): string;
expires?: Date | undefined;
httpOnly?: boolean | undefined;
maxAge?: number | undefined;
path?: string | undefined;
sameSite?: true | false | 'lax' | 'strict' | 'none' | undefined;
secure?: boolean | undefined;
}
Using with tRPC Nuxt
TRPC uses POST
requests for the mutation endpoints. Using the CSRF protection functionality of this module with trpc-nuxt will help you protect your mutation endpoints from CSRF.
In order to make the CSRF functionality of this module work with trpc-nuxt
, we have to add the CSRF token value into a csrf-token
header inside the outgoing request headers in our trpc
client.
import { createTRPCNuxtClient, httpBatchLink } from "trpc-nuxt/client";
import type { AppRouter } from "@/server/trpc/routers";
export default defineNuxtPlugin(() => {
const headers = useRequestHeaders();
const { csrf } = useCsrf();
const client = createTRPCNuxtClient<AppRouter>({
links: [
httpBatchLink({
// Headers are called on every request
headers() {
// Add CSRF token to request headers
return { ...headers, "csrf-token": csrf };
},
}),
],
});
return {
provide: {
client,
},
};
});