This is a complete authentication system built with Next.js and NextAuth.js, featuring login, registration, and protected routes with persistent file-based user storage.
├── app/
│ ├── api/auth/
│ │ ├── [...nextauth]/route.ts # NextAuth configuration and authorization
│ │ └── register/route.ts # Registration API endpoint (POST)
│ ├── auth/
│ │ ├── login/page.tsx # Login page
│ │ └── register/page.tsx # Registration page
│ ├── dashboard/page.tsx # Private protected page
│ ├── public/page.tsx # Public accessible page
│ ├── layout.tsx # Root layout with SessionProvider
│ ├── page.tsx # Home/landing page
│ └── providers.tsx # Auth provider wrapper
├── lib/
│ ├── auth.ts # Server-side auth helper
│ └── users.ts # File I/O utilities for users.json
├── middleware.ts # Route protection middleware
├── users.json # Persistent user database
├── .env.local # Environment variables
└── package.json
✅ Authentication System
- Credentials-based authentication (email + password)
- User registration with API endpoint
- Persistent file-based storage (users.json)
- Login with session management
- Automatic session creation after registration
- Logout functionality
- Email uniqueness validation
✅ Pages
- Home Page (
/) - Shows demo information and authentication status - Public Page (
/public) - Accessible to everyone - Login Page (
/auth/login) - User login via NextAuth - Register Page (
/auth/register) - User registration via API - Dashboard (
/dashboard) - Protected page (requires authentication)
✅ Security
- Middleware-based route protection
- Secure session management with JWT
- Password validation (minimum 6 characters)
- Email uniqueness checks
- Auth secret encryption
- Protected API routes
npm installThe .env.local file is already configured with:
NEXTAUTH_URL=http://localhost:3000
AUTH_SECRET=your-secret-key
For production, generate a secure secret:
openssl rand -base64 32npm run devServer will start at http://localhost:3000
The application uses a users.json file for persistent user storage:
[
{ "id": "1", "email": "user@example.com", "password": "password123", "name": "Demo User" },
{ "id": "2", "email": "admin@example.com", "password": "admin123", "name": "Admin User" }
]Important: This file-based storage is for demo purposes. For production:
- Use a proper database (PostgreSQL, MongoDB, etc.)
- Hash passwords with bcryptjs or argon2
- Implement proper security measures
Use these to test the authentication:
User Account:
- Email:
user@example.com - Password:
password123
Admin Account:
- Email:
admin@example.com - Password:
admin123
Or create a new account using the registration page.
- User visits
/auth/login - Enters email and password
- NextAuth validates credentials against
users.json - Match found → Session created with JWT cookie
- User redirected to
/dashboard - Session persists across page refreshes
- User visits
/auth/register - Fills in name, email, password, and confirmation
- Client-side validation (email format, password match, length)
- Form submitted to
POST /api/auth/registerAPI endpoint - Server-side validation:
- Password validation (minimum 6 characters)
- Email uniqueness check against
users.json
- Valid → New user added to
users.jsonwith auto-generated ID - Auto-login with credentials to create session
- User redirected to
/dashboard
- User tries to access
/dashboard - Middleware checks authentication status
- Not authenticated → Redirected to
/auth/login - Authenticated → Full access to protected page
- User clicks "Sign Out" button
- NextAuth clears session cookie
- User redirected to login page
- Dashboard no longer accessible
1. Visit http://localhost:3000/public without logging in
2. Page loads successfully
3. Visit while logged in
4. Page still accessible with session info displayed
✓ Verified: Public pages work for everyone
1. Visit http://localhost:3000/dashboard without login
2. Redirected to http://localhost:3000/auth/login
3. Enter credentials: user@example.com / password123
4. Redirected to /dashboard
5. Dashboard displays user information
✓ Verified: Protected routes redirect to login
1. Visit http://localhost:3000/auth/register
2. Fill in all fields with new account details
3. Click Register
4. Success message displayed
5. Auto-redirected to /dashboard after 1 second
6. New user visible in users.json
✓ Verified: Registration persists to file and auto-logs in
1. Login successfully to dashboard
2. Refresh the page (Ctrl+R)
3. Dashboard still accessible
4. Visit /public page
5. Session information still shown
6. Return to /dashboard
✓ Verified: Session persists across page navigation
1. While logged in on /dashboard
2. Click "Sign Out"
3. Redirected to /auth/login
4. Try accessing /dashboard directly
5. Redirected to /auth/login again
✓ Verified: Logout clears session properly
1. Go to register page
2. Try registering with existing email (user@example.com)
3. Error message: "Email already registered"
4. Try different email - registration succeeds
✓ Verified: Email duplication check works
- Purpose: NextAuth v4 configuration and route handlers
- Exports: GET/POST handlers for authentication
- Features:
- Credentials provider setup
- Reads users from
users.jsonviareadUsers() - JWT and session callbacks
- Error handling and logging
- Purpose: Custom registration API endpoint
- Method: POST
/api/auth/register - Request Body:
{ "email": "user@example.com", "password": "password123", "name": "User Name" } - Features:
- Server-side validation (password length, email format)
- Email uniqueness check against
users.json - New user creation with auto-generated ID
- Returns created user info (without password)
- Purpose: File I/O utilities for users.json
- Functions:
readUsers()- Read all users from filewriteUsers(users)- Write users to filefindUser(email)- Find user by emailaddUser(newUser)- Add new user to file
- Used by: NextAuth provider and registration API
- Purpose: Server-side session retrieval
- Function:
auth()- Gets current user session - Used by: Server components and page.tsx for session display
- Type: Client component
- Purpose: Registration form UI
- Features:
- Form validation (client-side)
- Calls
/api/auth/registerendpoint - Displays success/error messages
- Auto-login after successful registration
- Type: Client component
- Purpose: Login form UI
- Features:
- Email and password inputs
- Uses NextAuth
signIn()function - Error handling for invalid credentials
- Link to registration page
- Type: Server component
- Purpose: Protected dashboard page
- Features:
- Uses
auth()to check session - Redirects to login if not authenticated
- Displays user information from session
- Shows authentication flow explanation
- Uses
- Purpose: Client-side SessionProvider wrapper
- Wraps: Root layout component
- Enables:
useSession()hook in client components
- Purpose: Route protection middleware
- Routes Protected:
/dashboard/* - Features:
- Uses NextAuth
withAuthwrapper - Redirects to login if not authenticated
- Configured for App Router
- Uses NextAuth
- NEXTAUTH_URL: Application URL for callbacks
- AUTH_SECRET: Secret for encrypting tokens (required for security)
| Route | Method | Purpose | Authentication |
|---|---|---|---|
/api/auth/signin |
POST | Login via NextAuth | None |
/api/auth/callback/credentials |
POST | Handle credentials login | None |
/api/auth/signout |
POST/GET | Logout user | Session |
/api/auth/session |
GET | Get current session | Session |
/api/auth/providers |
GET | List auth providers | None |
/api/auth/register |
POST | Register new user | None |
- Next.js 16.1.6 - React framework with App Router
- React 19.2.3 - UI library
- TypeScript 5.x - Type safety
- NextAuth.js v4 - Authentication library
- Tailwind CSS 4 - Utility-first styling
- Node.js fs (promises) - File system operations
⚠️ Passwords stored in plain text in JSON file⚠️ No password hashing⚠️ No email verification⚠️ Single file storage (not scalable)
- Database Integration - Use PostgreSQL, MongoDB, etc.
- Password Hashing - Implement bcryptjs or argon2
- Email Verification - Send verification emails
- HTTPS - Always use HTTPS in production
- Environment Variables - Keep secrets in
.env.local - CSRF Protection - Enabled by default in NextAuth
- Rate Limiting - Implement on auth endpoints
- OAuth Providers - Add GitHub, Google sign-in
- Session Security - Use secure cookies and HTTPS
- Input Validation - Sanitize all user inputs
- Check browser DevTools Network tab for
/api/auth/callback/credentials - Verify email and password in
users.json - Check browser console for errors
- Ensure
NEXTAUTH_SECRETis set in.env.local
- Check
/api/auth/registerresponse in DevTools - Verify email is not already in
users.json - Check password meets minimum length (6+ characters)
- Check file system permissions for
users.json
- Verify
middleware.tsexists in root directory - Check route pattern in middleware config
- Look for middleware warning in dev server output
- Clear browser cache and cookies
- Ensure
AUTH_SECRETis set in.env.local - Check browser cookies (DevTools → Application → Cookies)
- Verify SessionProvider is wrapping all pages
- Check for errors in browser console
- Ensure file has read/write permissions
- Check disk space availability
- Verify file path is correct
- NextAuth.js v4 Documentation
- Next.js App Router
- Next.js Middleware
- TypeScript in Next.js
- Tailwind CSS
This is a demo/educational project for learning NextAuth.js + Next.js authentication patterns.