A robust authentication system built with Next.js, Prisma, and Neon PostgreSQL, featuring email verification, password reset, and rate limiting.
- 🔐 Secure user authentication
- ✉️ Email verification
- 🔑 Password reset functionality
- 🛡️ Rate limiting protection
- 🔒 Secure password hashing with bcrypt
- 🎫 JWT-based session management
- 📝 Input validation using Zod
- 🚦 Rate limiting for security
- 🗃️ PostgreSQL database with Prisma ORM
- Install dependencies:
bun install- Set up environment variables:
cp .env.example .envEdit .env with your configuration:
- Get a PostgreSQL database URL from Neon
- Get an API key from Resend for email services
- Generate a secure JWT secret
- Set your application URL
- Initialize the database:
bunx prisma db pushRegister a new user
{
"email": "[email protected]",
"password": "securepassword",
"name": "John Doe"
}Login with credentials
{
"email": "[email protected]",
"password": "securepassword"
}Verify email address
{
"token": "verification-token"
}Request password reset
{
"email": "[email protected]"
}Reset password with token
{
"token": "reset-token",
"password": "newpassword"
}- Password Hashing: Uses bcrypt for secure password storage
- Rate Limiting: Prevents brute force attacks
- JWT Tokens: Secure session management
- HTTP-Only Cookies: Prevents XSS attacks
- Input Validation: Prevents injection attacks
- Security Headers: Protection against common web vulnerabilities
- Email Verification: Prevents fake email registrations
- Login: 5 attempts per minute
- Register: 3 attempts per hour
- Forgot Password: 3 attempts per hour
- Reset Password: 3 attempts per hour
- Email Verification: 5 attempts per 5 minutes
DATABASE_URL= # Neon PostgreSQL connection URL
JWT_SECRET= # Secret key for JWT signing
RESEND_API_KEY= # Resend API key for emails
NEXT_PUBLIC_APP_URL= # Your application URL
NODE_ENV= # development/production
model User {
id String @id @default(uuid())
email String @unique
password String
name String?
emailVerified DateTime?
verificationToken String? @unique
resetToken String? @unique
resetTokenExpires DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}