Authentication with AI: Adding Login to Your Vibecoded App
A step-by-step guide to adding user authentication to your Next.js app using AI-assisted development — covering NextAuth, session management, and protected routes.
Authentication with AI: Adding Login to Your Vibecoded App
Authentication is the feature every real app needs and every beginner dreads. This guide walks you through adding login to a Next.js app with AI assistance — safely.
Why Auth Matters
Without authentication, every user sees the same thing and no data is personal. The moment you want:
- User-specific data (dashboards, profiles, saved items)
- Access control (admin vs. regular users)
- Personalization (settings, preferences)
...you need auth.
Choosing an Approach
For Next.js apps, your main options are:
| Approach | Pros | Cons | |----------|------|------| | NextAuth.js | Free, flexible, many providers | More setup | | Supabase Auth | Easy, includes database | Vendor lock-in | | Clerk | Beautiful UI components | Paid after free tier | | Custom JWT | Full control | Security risk if done wrong |
Our recommendation: Start with NextAuth.js (now called Auth.js). It's free, well-documented, and AI models generate good code for it.
Step 1: Install Dependencies
npm install next-auth
Step 2: Prompt for the Auth Config
Here's a prompt that generates a solid starting point:
"Create a NextAuth.js configuration for a Next.js app router application. Include:
- GitHub and Google OAuth providers
- A credentials provider with email/password
- JWT session strategy
- TypeScript types for the session
- The auth config file at lib/auth.ts
- The route handler at app/api/auth/[...nextauth]/route.ts"
Step 3: Review the Generated Code
AI will generate the auth config, but you MUST check:
Environment Variables
Make sure the config reads from environment variables, not hardcoded values:
// GOOD
clientId: process.env.GITHUB_ID!,
clientSecret: process.env.GITHUB_SECRET!,
// BAD — never commit secrets
clientId: "abc123",
clientSecret: "secret456",
Session Handling
Verify the session callback includes the data you need:
callbacks: {
session: ({ session, token }) => ({
...session,
user: {
...session.user,
id: token.sub,
},
}),
},
Password Hashing
If using credentials auth, ensure passwords are hashed:
import bcrypt from "bcryptjs";
// When creating a user
const hashedPassword = await bcrypt.hash(password, 12);
// When verifying
const isValid = await bcrypt.compare(password, user.hashedPassword);
Never store plain-text passwords. If the AI generates code that stores passwords without hashing, fix it immediately.
Step 4: Protect Your Routes
Server Components
import { auth } from "@/lib/auth";
import { redirect } from "next/navigation";
export default async function DashboardPage() {
const session = await auth();
if (!session) redirect("/login");
return <div>Welcome, {session.user?.name}</div>;
}
API Routes
import { auth } from "@/lib/auth";
import { NextResponse } from "next/server";
export async function GET() {
const session = await auth();
if (!session) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
// ... handle authenticated request
}
Middleware (Protect Multiple Routes)
export { auth as middleware } from "@/lib/auth";
export const config = {
matcher: ["/dashboard/:path*", "/settings/:path*"],
};
Step 5: Build the Login UI
Prompt the AI for a login page:
"Create a login page with email/password form and OAuth buttons for GitHub and Google. Use the signIn function from next-auth/react. Include error handling for invalid credentials. Dark theme with Tailwind CSS."
Security Checklist
Before shipping auth to production:
- [ ] Environment variables are set (not hardcoded)
- [ ] Passwords are hashed with bcrypt (12+ rounds)
- [ ] CSRF protection is enabled (NextAuth does this by default)
- [ ] Session expiry is configured (don't use infinite sessions)
- [ ] OAuth redirect URLs are whitelisted
- [ ] Error messages don't reveal whether an email exists
- [ ] Rate limiting is in place on the login endpoint
- [ ] HTTPS is enforced in production
Common AI Mistakes to Watch For
- Hardcoded secrets — AI sometimes puts example API keys in the code
- Missing password hashing — credentials providers without bcrypt
- Overly permissive callbacks — session callbacks that expose internal IDs
- No error handling — login forms that show raw error objects
- Missing CSRF tokens — custom implementations that skip CSRF protection
Next Steps
Once auth is working:
- Add role-based access (admin, user, guest)
- Set up email verification for credentials accounts
- Add password reset flow
- Consider two-factor authentication for sensitive apps
Authentication is one of the most security-critical features in any app. Use AI to generate the boilerplate, but always review the security aspects manually.
Stay in the flow
Get vibecoding tips, new tool announcements, and guides delivered to your inbox.
No spam, unsubscribe anytime.