Technically
AI Reference
Your dictionary for AI terms like LLM and RLHF
Company Breakdowns
What technical products actually do and why the companies that make them are valuable
Learning Tracks
In-depth, networked guides to learning specific concepts
Posts Archive
All Technically posts on software concepts since the dawn of time
Terms Universe
The dictionary of software terms you've always wanted

Explore learning tracks

AI, it's not that ComplicatedAnalyzing Software CompaniesBuilding Software ProductsWorking with Data Teams
Loading...
I'm feeling luckyPricing
Log In

Software Eng for Vibe Coders: Auth + Security

How to make sure anyone on the internet can't just delete your app's data, and other security considerations.

Last updated Sep 8, 2026cybersecurity
David Krevitt
David Krevitt
Read within learning track:Software Engineering for Vibe Coders

Vibe coding is amazing. But do you actually understand what you've built, so you can maintain and improve it over time?

This 6-part Technically series, Software Engineering for Vibe Coders, teaches you everything you need to know about how the apps you're vibe coding work under the hood, and (crucially) how they might break as your user base scales.

Thanks to our friends at Railway, who help you peacefully deploy those vibe coded apps, for sponsoring this series. Spin up anything your vibe coded app might need at railway.com/new.

ICYMI, check out:

  • Part 1 (on frontends + backends)
  • Part 2 (on database + storage)

The TL;DR#

Auth is how your app knows who’s using it and what they’re allowed to touch:

  • Authentication (“Authn”) proves who you are by forcing you to log in.
  • Authorization (“Authz”) decides what you can and can’t do once you’re logged in.
  • Authorization is often managed with role-based access control (RBAC): permissions attach to roles (admin, staff, supplier), not to individual people. Also a Gaelic term for “a very tedious thing to maintain.”
  • Row-level security (RLS) is another way of enforcing authorization at the database level, so you can’t view other people’s data.

The classic vibe-coded app security incident isn't really getting "hacked." It's a user walking through a door you left open. Latex-thin, at best. Let's lock the doors.

Terms Mentioned

Frontend

Training

Backend

API

Endpoint

Authentication

Web App

Database

Query

Companies Mentioned

Okta logo

Okta

OKTA

Previously, at Vandelay Industries#

Art Vandelay is building an app that runs Vandelay Industries's potato chip import/export empire. It lets suppliers do business with Vandelay without him having to talk on the phone (which for some reason kills deals).

Loading image...

In Part 1 we built a frontend and a backend, which talk to each other through an API. In Part 2 we gave it a memory, a Postgres database on Railway, now filling up with supplier applications.

But there’s one small problem. Here's Art's "private" dashboard:

Loading image...

I put "private" in quotes because nothing about it is private, because Art forgot to add a login. Anyone with the URL - a competitor, a bored teenager, Newman - can read every application + every shipment.

So now Art needs to lock it down. He wants suppliers to sign in and be able to check only their own application status. Art also needs the dashboard locked to himself. And Newman must never, under any circumstances, see the shipping schedule.

All of that is the mythical "auth" you’ve heard about, which is really two separate jobs, as engineers that work on auth are always pointing out.

Authentication vs authorization#

Authentication is proving you are who you claim to be. Anyone can claim to be a marine biologist, but authentication requires you to prove it, by logging in if we’re talking about a web app.

Loading image...

A few years ago, authentication was actually tedious to set up, but it’s now a solved problem. Providers like Clerk (which Art used for his app) make this super easy.

You will see people on X poo-pooing auth providers and saying they can just "roll their own." And perhaps they can. But you can't. And they probably can't either.

Clerk hands you two API keys, you add them to your app (by setting environment variables on Railway, or in your local .env file), and you have working login + signup pages on your app (including the much loved “Sign in with Google”, bc who needs another password).

One of those keys (the "publishable" one) is safe to expose in your frontend. The other (the secret key) must never leave your environment variables, which we store securely in Railway.

And since it's probably your coding agent doing this wiring, not you: Clerk ships an MCP server and a set of agent Skills, so your agent pulls current, correct patterns straight from the source instead of guessing at Clerk's API from year-old training data. Auth is the last place you want your agent hallucinating.

Loading image...

But then the real fun starts, of controlling what users who log in can actually do.

Authorization is what a verified person is allowed to do. Puddy can log in to the app, but he can’t approve his own supplier application.

Authorization is much more complicated than authentication, because there are basically unlimited permutations of roles (admin, user, superuser, superadmin) and activity levels to account for.

Authorization is the half of auth that vibe coders like Art actually get burned by, in 2 ways:

  1. Not blocking pages + data that shouldn’t be accessible by a given user
  2. Blocking too much and providing a poor user experience

#2 is a real risk. Authorization requires really gaming out options before you commit, like ordering off the Cheesecake Factory menu.

The authorization plan#

Gaming it out can be embarrassingly low-tech, literally making a table of roles + features those roles should have access to, like so:

Loading image...

Each column is a role, and each row is a feature. The cells are ownership: whose data a given role can act on for that feature.

Kramer can view applications, but only for Kramerica Industries. Coding agents can figure this stuff out, but you’re really better off being clear about what you need here. And it only gets more important as the feature set in your app grows over time.

Would you order “surprise me” off the Cheesecake Factory menu?

Are you on the list?#

A rule from Part 1 of this series is worth tattooing somewhere your mom can't see: never trust the frontend.

The frontend runs in the user's browser, and the user controls their browser. Anything you "hide" there can be un-hidden with dev tools — or skipped entirely by calling your API directly.

When a user does something in the Vandelay App (like view a supplier application), the request passes through three separate stages: the page route they visit (/applications/1002), the API endpoints that page calls to fetch data (/api/applications/1002), and the database query the backend runs to actually get the relevant rows.

Your backend has two places (that we know of) to enforce authorization along the way:

1. On the page route + API call. Both check the same two things: whether a) the authenticated user’s role should be able to view applications, and b) whether the application in question (id 1002) belongs to the user’s organization (Kramerica Industries).

If you skip that second check, any logged-in user can read any other user's data just by changing the number in the URL. Another supplier pulls up /applications/1002, and now he's reading Kramerica Industries' pitch. And taking notes.

🚨 Confusion Alert

The subtle part is that pages and API endpoints are separate ways to access the same data, and protecting the page does not protect the endpoint underneath it.

This is what middleware is for: it applies authorization checks across every route by default, so a new endpoint call can’t be run unprotected.

2. In the database. Postgres offers row-level security (RLS), which attaches the rule to the table itself. Suppliers can only see application rows matching their org_id, which is passed directly from authentication.

This isn’t hypothetical btw. In 2025, a security researcher scanned 1,645 vibe-coded apps and found 170 with missing or unenforced RLS. Tables of emails, API keys, and payment data, readable by anyone.

It’s possible to have too much of a good thing though - if you over-configure too many RLS rules, no one will be able to see any data.

What breaks when the suppliers show up#

Some auth problems, just like database problems, are invisible while you're testing and guaranteed once real users arrive.

Kicking someone out. A supplier emails Art to say their laptop was stolen, and Art needs that laptop logged out of the app immediately.

Whether he can do that depends on plumbing he's never thought about: when someone logs in, the app keeps them logged in with a session token stored in their browser.

Thankfully auth providers like Clerk offer a "sign out of all devices" button for every user, but if you’re managing auth some other way this could be difficult.

Feature creep. With coding agents, adding new features seems cheap - you type an instruction and it’s done.

But each new feature also expands your authorization requirements, and your logic can become unintelligible pretty quickly.

A month in, Art asks his coding agent for an export button so he can pull applications into a spreadsheet. The agent adds a new endpoint (/api/applications/export) that generates the CSV, but now that endpoint needs an authorization plan. Can only admins export, or can bookkeepers too?

The decision isn’t super clear - it’s not something you want to just leave up to a coding agent.

Requests for more login methods. If the app is really successful with larger Suppliers, they might ask Art to turn on SSO (single sign-on), so that their entire company can log in without having to manually create accounts for yet another app.

An entire software category, including companies like Okta and now WorkOS, exists to solve that problem, and enterprise features like SSO can unlock larger revenue opportunities (but again require effort to implement properly).

Where that leaves Art (and you)#

So auth (both authentication + authorization) is now handled, for today’s feature set anyway.

Clerk tells the app who’s at the door, and Art didn’t really have to build much (other than dropping an API key in Railway).

The app now knows the difference between Art, the bookkeeper, Kramer, and Newman.

Hello, Newman. No, you can't see the manifest.

Loading image...
Up Next
Software Eng for Vibe Coders: Databases + StorageFree

Where your vibe coded app actually keeps its data, and how it might break when real users show up.

Software Eng for Vibe Coders: On Frontends + BackendsFree

A new series to help non-engineers build products that can handle going viral.

Content
  • All Posts
  • Learning Tracks
  • AI Reference
  • Companies
  • Terms Universe
Company
  • Pricing
  • Sponsorships
  • Contribute
  • Contact
Connect
SubscribeSubstackYouTubeXLinkedInInstagram📞Call for advice
Legal
  • Privacy Policy
  • Terms of Service

© 2026 Technically.