Auth Security – Keeping Users' Data Safe

You built auth with Clerk and stored user data in Neon. Now verify it's actually secure before you ship to production.

The bottom line: each user's data is locked to that user. User A can never see User B's data – even if they try.

Where you are: you've been building and testing on your auth branch's preview. Verify security there, then deploy to production in the next lesson.

1. Understand the security model

Two parts work together:

Authentication: proving who you are (Clerk)

Like showing ID to prove you're Alice. When a user signs in, Clerk verifies them and issues a secure session – proof of "this is Alice." You don't build this; Clerk handles passwords, sessions, and security.

Authorization: what you can access (your server + Neon)

This is the part you are responsible for, and it's why the last lesson mattered. Neon is a plain database – it doesn't magically hide one user's rows from another. Instead, your server enforces it: on every request, it checks the Clerk session and only ever queries that user's rows.

How it works together

  1. User signs in → Clerk proves "this is Alice."
  2. Alice requests data → your server checks the Clerk session (auth()).
  3. The server queries Neon filtered to Alice's id → only Alice's data comes back.
  4. Because every data path goes through that server-side check, there's no way to reach someone else's rows.

The key insight: identity comes from Clerk; access control lives in your server code (which the Clerk skill set up correctly). Keep every database read and write behind that server-side check.

Outcome: You understand how Clerk plus server-side checks keep data isolated.

I understand the security model (Clerk + server-side access)

2. Verify data isolation actually works

This is the single most important check – test that users genuinely can't see each other's data, on your preview.

Test that users can't see each other's data
Help me test data isolation on my preview, in three steps:
1.**As User A:** sign in as user-a@test.com and create a few records. Note what you made.
2.**As User B:** sign out, sign in as user-b@test.com, and look at the app.
3.**Verify:** User B must NOT see any of User A's data, only their own.
Report what User A created and what User B can see, and whether isolation holds. If User B can see User A's data, stop and fix the server-side check before we go further.

Outcome: You've confirmed each user only sees their own data.

I tested and verified data isolation works

3. Auth security rules to follow

A few habits keep things safe as you grow.

Secrets live in Vercel, never in code

Your secrets – Clerk keys and your Neon DATABASE_URL – belong in the Vercel vault, pulled down to .env.local (which stays out of Git). Never hardcode them, never paste them into chat or screenshots.

Check that my secrets are protected
Verify my secrets are safe:
1.Confirm no secrets (Clerk keys, DATABASE_URL, any key) are hardcoded anywhere in my code.
2.Confirm .env.local is git-ignored and was never committed (check the history).
3.Confirm all required secrets are set in Vercel for production.
Report what you found and fix anything that's off.

Before every deploy

  • Secrets are set in Vercel for production.
  • The data-isolation test still passes (User A vs User B).
  • No secrets visible in code.
  • Users can sign in and out smoothly.

These few checks prevent the large majority of security problems.

Outcome: You understand and follow the essential auth security rules.

I follow the essential auth security rules