Clark Heal Carreon
Back to All Posts
Web Development

5 Essential Security Practices for Next.js Applications

Clark Heal Carreon
5 Essential Security Practices for Next.js Applications

As a full-stack developer, I, Clark Heal Carreon, believe that security is a core responsibility. With Next.js, many security best practices are handled for you, but there are still critical areas you must manage yourself. Here are five essential practices.

1. Validate All User Input

Never trust user input. Whether it's from a form or an API request, all incoming data must be validated on the server. Libraries like Zod make this easy by defining a schema and ensuring data conforms to it before processing.

  • Use Zod with Server Actions:
'use server';
import { z } from 'zod';

const schema = z.object({
  email: z.string().email(),
});

export async function subscribe(formData: FormData) {
  const result = schema.safeParse({ email: formData.get('email') });
  if (!result.success) {
    // Handle validation error
    return { error: 'Invalid email' };
  }
  // Proceed with valid data
}

2. Protect Your API Routes and Server Actions

Not all server-side logic should be public. Protect sensitive endpoints by verifying the user's session or authentication status before executing any code.

  • Check Authentication:
import { auth } from '@/lib/auth'; // Your auth utility

export async function POST(req: Request) {
  const session = await auth(); // Get the user's session
  if (!session?.user) {
    return new Response('Unauthorized', { status: 401 });
  }
  // Proceed with protected logic
}

3. Use Environment Variables for Secrets

Never hardcode API keys, database credentials, or other secrets directly in your code. Use environment variables. Next.js has built-in support for them.

  • Server-Side Only: Prefix variables with `NEXT_PUBLIC_` ONLY if they need to be accessible in the browser. All other variables are server-side by default, which is more secure.

```.env.local
DATABASE_URL="postgresql://..."
GITHUB_SECRET="your_secret_key"
NEXT_PUBLIC_ANALYTICS_ID="your_public_key"
```

4. Set Secure HTTP Headers

Use a tool like the Next.js `headers` function in your `next.config.js` to set important security headers. These headers instruct the browser on how to behave, preventing attacks like clickjacking and cross-site scripting (XSS).

  • Example in `next.config.js`:

```javascript
const securityHeaders = [
{
key: 'X-Content-Type-Options',
value: 'nosniff'
},
{
key: 'X-Frame-Options',
value: 'SAMEORIGIN'
}
];

async headers() {
return [
{
source: '/:path*',
headers: securityHeaders,
},
];
}
```

5. Keep Dependencies Updated

Vulnerabilities are often found in third-party packages. Regularly update your dependencies to ensure you have the latest security patches. Use tools like `npm audit` or GitHub's Dependabot to automatically scan for and alert you to vulnerabilities.

Conclusion

Security is an ongoing process, not a one-time setup. By validating input, protecting routes, managing secrets, setting headers, and updating dependencies, you can build a strong security foundation for your Next.js applications and protect both your product and your users.

Security
Next.js
Web Security
Authentication
Clark Heal Carreon