Data Validation in the Next.js Supabase Turbo kit
Learn how to validate data in the Next.js Supabase Turbo kit.
Data Validation is a crucial aspect of building secure applications. In this section, we will look at how to validate data in the Next.js Supabase Turbo kit.
Steps to validate data
Learn how to validate data in the Next.js Supabase Turbo kit.
What are we validating?
A general rule, is that all client-side provided data should be validated/sanitized. This includes:
- URL parameters
- Search params
- Form data
- Cookies
- Any data provided by the user
Using Zod to validate data
The Next.js Supabase Turbo kit uses Zod to validate data. You can use the z object to validate data in your application.
import * as z from "zod";const userSchema = z.object({ id: z.string(), name: z.string(), email: z.string().email(),});// Validate the dataconst validatedData = userSchema.parse(data);Validating payload data to Server Side API
We generally use two ways for sending data from a client to a server:
- Server Actions
- API Route Handlers
Let's look at how we can validate data for both of these cases.
Server Actions: Using authActionClient
The authActionClient creates type-safe server actions with built-in Zod validation and authentication.
'use server';import { authActionClient } from "@kit/next/safe-action";import * as z from "zod";const UserSchema = z.object({ id: z.string(), name: z.string(), email: z.string().email(),});export const createUserAction = authActionClient .inputSchema(UserSchema) .action(async ({ parsedInput, ctx: { user } }) => { // parsedInput is now validated against the UserSchema // do something with the validated data });When you define an action using authActionClient, the parsedInput is validated against the schema automatically. The ctx.user provides the authenticated user.
API Route Handlers: Using the "enhanceRouteHandler" utility
The enhanceRouteHandler hook is a utility hook that enhances Next.js API Route Handlers with Zod validation.
import { enhanceRouteHandler } from "@kit/next/routes";import * as z from "zod";const UserSchema = z.object({ id: z.string(), name: z.string(), email: z.string().email(),});export const POST = enhanceRouteHandler(async ({ body, user, request }) => { // body is now validated against the UserSchema // user is the authenticated user // request is the incoming request // do something with the validated data}, { schema: UserSchema, auth: true,});Very similar to authActionClient, the enhanceRouteHandler utility enhances the handler function with Zod validation and authentication.
When you define an API route using enhanceRouteHandler, the body argument is validated against the schema option automatically. The user argument provides the authenticated user, and request is the incoming request object.
Validating Cookies
Whenever you use a cookie in your application, you should validate the cookie data.
Let's assume you receive a cookie with the name my-cookie, and you expect it to be a number. You can validate the cookie data as follows:
import * as z from "zod";import { cookies } from "next/headers";const cookieStore = await cookies();const cookie = z.coerce.number() .safeParse(cookieStore.get("my-cookie")?.value);if (!cookie.success) { // handle the error or provide a default value}Validating URL parameters
Whenever you receive a URL parameter, you should validate the parameter data. Let's assume you receive a URL parameter with the name my-param, and you expect it to be a number. You can validate the parameter data as follows:
interface PageProps { searchParams: Promise<{ myParam: string }>;}async function Page({ searchParams }: PageProps) { const params = await searchParams; const param = z.coerce.number() .safeParse(params.myParam); if (!param.success) { // handle the error or provide a default value } // render the page with the validated data}Going forward, remember to validate all data that you receive from the client, and never trust anything the client provides you with. Always have a default value ready to handle invalid data, which can prevent potential security issues or bugs in your application.
Upgrading from v2
In v2, server actions used enhanceAction from @kit/next/actions and Zod was imported as import { z } from 'zod'. In v3, server actions use authActionClient from @kit/next/safe-action and Zod is imported as import * as z from 'zod'.
For the full migration guide, see Upgrading from v2 to v3.