SecureAuth Starter is a security-focused full-stack authentication system built as a portfolio project demonstrating secure software engineering practices. It uses a production-style architecture with a Next.js frontend, Express API, PostgreSQL/Prisma data model, Redis-backed sessions and rate limits, and security-focused automated tests.
It is intentionally more than a fake login screen or UI-only demo. The backend owns authentication state, hashes passwords with Argon2id, stores opaque session IDs in HTTP-only cookies, enforces CSRF and RBAC controls, and writes audit events for sensitive actions.
This project is designed for software engineering, application security, and DevSecOps portfolio review. It is a local starter/reference implementation, not a fully deployed production identity platform.
If you only have five minutes:
- Read What This Project Proves to understand the engineering signal.
- Skim Architecture, Threat Model, and OWASP Mapping for the security model.
- Run it locally with the commands in Running Locally.
- Run the automated checks with
npm test; usenpm run lint,npm run typecheck, andnpm run auditfor the full local verification set. - Review Project Screenshots for proof of the main flows and verification evidence.
The screenshots show:
- Login and registration UI
- Protected dashboard after authentication
- Admin-only user management and RBAC behavior
- Email verification and password reset flows through the dev mailbox
- Automated security tests passing
- Lint/type/audit checks passing
- Stored password hash prefix proving Argon2id hashing
Security concepts demonstrated:
- Argon2id password hashing
- HTTP-only cookie sessions
- Redis-backed sessions and rate limiting
- CSRF protection for state-changing requests
- RBAC and admin-only routes
- Audit logging for sensitive actions
- PostgreSQL/Prisma data modeling
- Docker-based local infrastructure
- Security-focused automated tests
SecureAuth Starter is a portfolio and security engineering project. It demonstrates production-style authentication architecture and implementation patterns, but it is not a fully deployed production identity platform.
Production use would require additional operational work, including:
- Real email provider for verification and password reset delivery
- TLS termination and secure production hosting
- Monitoring, alerting, and centralized log handling
- Secret rotation and production secret management
- Database backups and restore testing
- CAPTCHA or risk-based controls for public authentication endpoints
- Operational hardening for infrastructure, deployments, and incident response
- Secure registration, login, logout, email verification, and password reset flows
- Argon2id password hashing
- HTTP-only cookie-based sessions
- Redis-backed session storage
- Redis-backed rate limiting
- CSRF protection for state-changing requests
- Role-based access control with
USERandADMINroles - Admin-only user management
- Audit logging for security-sensitive actions
- Zod request validation
- Prisma-backed PostgreSQL data layer
- Docker Compose local infrastructure
- Automated backend and frontend security-focused tests
- Linting, type checking, and dependency audit verification
This repository demonstrates secure software engineering practices around authentication and authorization:
- Secure authentication beyond a fake login screen
- Argon2id password hashing instead of plaintext or fast hashes
- HTTP-only cookie sessions with server-side session state
- Redis-backed sessions and rate limiting
- CSRF protection on state-changing requests
- RBAC with
USERandADMINroles - Admin-only access for user management
- Audit logging for sensitive authentication and admin actions
- PostgreSQL/Prisma data modeling for users, tokens, sessions, and audit logs
- Docker-based local infrastructure for PostgreSQL and Redis
- Security-focused automated tests for authentication edge cases
- Honest production-hardening tradeoffs instead of claiming the demo is production-ready
- Next.js
- React
- TypeScript
- Credentialed API requests
- CSRF-aware form submissions
- Node.js
- Express
- TypeScript
- Prisma ORM
- Zod
- Argon2id
- Redis
- PostgreSQL
- Redis
- Docker Compose
- Environment-based configuration
- Vitest
- React Testing Library
- ESLint
- TypeScript type checking
- npm audit
Authentication is one of the most security-critical parts of any software product. Many portfolio projects implement login as a simple database check, store tokens insecurely in the browser, or ignore abuse controls entirely.
SecureAuth Starter takes a stronger approach. It demonstrates how authentication can be designed when security matters:
- Passwords are never stored in plaintext.
- Sessions are stored server-side and invalidated on logout.
- Cookies are HTTP-only.
- User input is validated at the API boundary.
- Authentication flows reduce account enumeration risk.
- Sensitive tokens are hashed at rest.
- Admin routes enforce role-based access control.
- Security events are logged for auditability.
- Rate limits reduce brute-force and credential-stuffing risk.
Browser
|
| HTTPS in production
| HTTP-only SameSite cookies
v
Next.js Web App :3000
|
| credentialed fetch
| x-csrf-token for state-changing requests
v
Express API :4000
|
|-- Zod request validation
|-- CSRF protection
|-- Redis rate limits
|-- Redis session store
|-- Argon2id password hashing
|-- Prisma data access
|-- RBAC middleware
|-- Audit logging
|
+--> PostgreSQL
|
+--> Redis
|
+--> Local development mailbox
- User registration
- User login and logout
- Email verification flow
- Password reset flow with one-time tokens
- Server-side sessions
- HTTP-only cookie authentication
- Role-based access control
- Admin-only user management
- Protected dashboard
- Audit logging
- Redis rate limiting
- CSRF protection
- Secure environment validation
- Passwords are hashed with Argon2id.
- Plaintext passwords are never stored.
- Passwords are never logged.
- Optional server-side password pepper is supported.
- Password reset tokens are hashed at rest.
- Password reset tokens are single-use and expire.
- Sessions are stored server-side in Redis.
- The browser receives only an opaque HTTP-only cookie.
- Cookies use
SameSite=Lax. - Cookies use
Securein production. - Session ID is rotated after login.
- Sessions are invalidated on logout.
- Password reset invalidates active sessions.
- Idle timeout and absolute session expiration are supported.
- Request bodies are validated with Zod.
- Authentication routes use generic responses where account enumeration matters.
- Login, registration, reset, and verification flows are rate limited.
- Repeated failed login attempts trigger additional throttling.
- State-changing requests require CSRF protection.
- Error handling avoids leaking stack traces in production.
- Environment variables are validated during startup.
- Authenticated routes require a valid session.
- Admin routes require the
ADMINrole. - Normal users cannot access admin-only resources.
- User-specific access checks prevent users from reading or modifying other users' data.
Audit logs are created for important security events, including:
- Registration
- Login success
- Login failure
- Logout
- Email verification
- Password reset request
- Password reset completion
- Admin role changes
- Admin user management actions
Audit logs avoid storing passwords, cookies, raw tokens, or secrets.
- Password hashes
- Session identifiers
- CSRF tokens
- Password reset tokens
- Email verification tokens
- User roles
- Audit logs
- Environment secrets
| Threat | Mitigation |
|---|---|
| Password theft | Argon2id hashing, no plaintext password storage, no password logging |
| Credential stuffing | Redis-backed rate limits and failed-login throttling |
| Session theft | HTTP-only cookies, server-side sessions, session invalidation |
| CSRF | CSRF token required for state-changing requests |
| Account enumeration | Generic responses for sensitive auth flows |
| Token replay | Reset and verification tokens are hashed and consumed once |
| Broken access control | Auth middleware, admin middleware, ownership checks |
| SQL injection | Prisma query APIs and Zod validation |
| Secret leakage | .env ignored, environment validation, no secret logging |
| Weak operational visibility | Audit logs for authentication and admin actions |
This project demonstrates practical controls related to the OWASP Top 10:
| OWASP Category | Project Controls |
|---|---|
| A01 Broken Access Control | requireAuth, requireAdmin, ownership checks |
| A02 Cryptographic Failures | Argon2id password hashing, signed cookies, hashed tokens |
| A03 Injection | Prisma ORM, Zod validation, no unsafe raw SQL |
| A04 Insecure Design | Threat model, token expiry, single-use reset tokens |
| A05 Security Misconfiguration | Helmet headers, environment validation, production cookie settings |
| A07 Identification and Authentication Failures | Rate limits, session rotation, logout invalidation |
| A09 Security Logging and Monitoring Failures | Audit logging for authentication and admin events |
SecureAuth-Starter/
apps/
api/
prisma/
schema.prisma
seed.ts
migrations/
src/
config/
middleware/
routes/
services/
tests/
app.ts
server.ts
.env.example
web/
src/
app/
assets/
components/
lib/
.env.example
docker-compose.yml
package.json
README.md
.gitignore
Install:
- Node.js 20+
- npm
- Docker Desktop
- Git
Docker Desktop must be running before starting PostgreSQL and Redis.
Create the API environment file:
cp apps/api/.env.example apps/api/.envOn Windows PowerShell:
Copy-Item apps\api\.env.example apps\api\.envExample local API environment:
DATABASE_URL="postgresql://secureauth:secureauth@localhost:5432/secureauth?schema=public"
REDIS_URL="redis://localhost:6379"
SESSION_SECRET="replace-with-a-long-random-secret"
ADMIN_EMAIL="admin@test.com"
ADMIN_PASSWORD="AdminPassword123!ChangeMe"
NODE_ENV="development"
PORT="4000"
WEB_ORIGIN="http://localhost:3000"Generate a strong local session secret:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"For the web app:
cp apps/web/.env.example apps/web/.env.localOn Windows PowerShell:
Copy-Item apps\web\.env.example apps\web\.env.localExample local web environment:
NEXT_PUBLIC_API_URL="http://localhost:4000"Never commit real .env files.
Install dependencies:
npm installStart PostgreSQL and Redis:
docker compose up -dVerify containers are running:
docker psGenerate Prisma client:
npm run prisma:generateRun database migrations:
npm run prisma:migrateSeed the admin user:
npm run prisma:seedStart the API:
npm run dev -w apps/apiIn another terminal, start the web app:
npm run dev -w apps/webOpen:
http://localhost:3000
The API runs at:
http://localhost:4000
If your .env uses the example values, the seeded admin account is:
Email: admin@test.com
Password: AdminPassword123!ChangeMe
Change these values before using the project outside local development.
Run the test suite:
npm testRun the full local verification suite:
npm run lint
npm run typecheck
npm run auditBackend security tests cover:
- Successful registration
- Duplicate registration safety
- Password hashing
- Login success
- Login failure
- Login rate limiting
- Logout invalidation
- Protected route rejection
- Admin route authorization
- One-time password reset tokens
- Expired reset token rejection
- Generic reset responses
Frontend tests verify:
- CSRF-aware form submission
- Basic auth-related UI behavior
After starting the app locally, verify the main security flows:
- Register a new user.
- Open the development mailbox.
- Use the email verification link.
- Log in as the verified user.
- Confirm the dashboard is accessible.
- Try accessing the admin page as a normal user and confirm access is denied.
- Log in as the seeded admin user.
- Open the admin user management page.
- Request a password reset.
- Use the reset link once.
- Try using the same reset link again and confirm it fails.
- Attempt repeated failed logins and confirm rate limiting.
- Inspect the database and confirm passwords are stored as Argon2id hashes.
- Inspect audit logs and confirm sensitive values are not stored.
You can verify that stored passwords are hashed with Argon2id:
docker exec -it secureauth-postgres psql -U secureauth -d secureauthThen run:
SELECT id, role, LEFT("passwordHash", 10) AS hash_prefix
FROM "User"
LIMIT 5;Expected hash prefix:
$argon2id$
Do not expose full password hashes, reset tokens, cookies, or secrets in screenshots.
The local development environment uses:
- PostgreSQL on port
5432 - Redis on port
6379
Expected container names:
secureauth-postgres
secureauth-redis
Stop services:
docker compose downStop and remove local volumes:
docker compose down -vUse down -v only if you want to delete local database data.
This project is suitable as a secure development portfolio project, but production deployment requires additional operational work.
Before production, add or verify:
- Real email provider for verification and password reset delivery
- TLS termination through a trusted provider
NODE_ENV=production- Strong production secrets
- Secret rotation process
- Hosted PostgreSQL with backups
- Hosted Redis with persistence and access controls
- Centralized logging and alerting
- Stricter Content Security Policy for final domains
- Monitoring for suspicious login and reset activity
- CAPTCHA or risk-based challenges for public authentication endpoints
- Database migration review process
- Dependency update process
- CI/CD secret scanning
- Production incident response plan
The local development mailbox must not be enabled in production.
No authentication system is complete without operational security. This project demonstrates secure implementation patterns, but it does not claim to solve every production security requirement.
Known limitations:
- No real email provider is configured by default.
- No MFA is implemented yet.
- No external SIEM integration is included.
- No CAPTCHA or bot protection is included.
- No cloud infrastructure module is included.
- No production backup policy is included.
- No formal third-party penetration test has been performed.
- Add MFA using TOTP or WebAuthn.
- Add device and session management.
- Add account lockout policy with admin unlock.
- Add suspicious login detection.
- Add IP reputation checks.
- Add email delivery provider integration.
- Add OpenTelemetry tracing.
- Add SIEM export support.
- Add Docker image signing with Sigstore Cosign.
- Add SBOM generation in CI.
- Add OpenSSF Scorecard checks.
- Add SAST and dependency scanning in CI.
SecureAuth Starter demonstrates practical secure software development skills, including:
- Secure authentication design
- Password hashing
- Session security
- CSRF protection
- Rate limiting
- RBAC
- Audit logging
- Secure environment handling
- OWASP-aligned engineering practices
- Security-focused automated testing
This project is intended to support a software engineering, application security, or DevSecOps portfolio.
MIT License.






