Full implementation of Kenmon authentication in a Next.js application with PostgreSQL and Drizzle ORM.
- Node.js 20 or higher
- Docker and Docker Compose
- npm or yarn
From the project root directory, start the PostgreSQL container:
docker-compose up -dThis will start a PostgreSQL 16 container on port 5432 with:
- Database:
kenmon_dev - User:
kenmon - Password:
kenmon_dev_password
Copy the example environment file and update it with your values:
cd examples/nextjs
cp .env.example .envThe default .env should contain:
DATABASE_URL=postgres://kenmon:kenmon_dev_password@localhost:5432/kenmon_dev
SESSION_SECRET=your-secret-key-here-change-me-in-productionnpm installUse Drizzle Kit to push the schema to your database:
npm run db:pushAlternatively, you can generate and run migrations:
npm run db:generate
npm run db:migratenpm run devOpen http://localhost:3000 in your browser.
npm run db:generate- Generate migration files from schemanpm run db:migrate- Run migrationsnpm run db:push- Push schema changes directly to database (useful for development)npm run db:studio- Open Drizzle Studio to browse your database
The application uses the following tables:
id(UUID, primary key)email(string, unique)created_at(timestamp)updated_at(timestamp)
id(UUID, primary key)user_id(UUID, foreign key to users)token(text)expires_at(timestamp)invalidated(boolean)ip_address(string, optional)user_agent(text, optional)created_at(timestamp)updated_at(timestamp)
id(UUID, primary key)email(string)code(string)expires_at(timestamp)used(boolean)created_at(timestamp)
Client-side automatic session refresh using the SessionRefresh component:
// src/app/layout.tsx
<SessionRefresh refreshInterval={86400} />The component automatically refreshes sessions based on the configured interval (24 hours by default).
Sessions capture IP address from request headers:
// src/lib/auth/utils.ts
export function getIPAddress(headers: Headers): string | undefined {
return (
headers.get('x-forwarded-for')?.split(',')[0] ||
headers.get('x-real-ip') ||
undefined
)
}Separate storage classes for sessions and OTP using Drizzle ORM:
DrizzleSessionStorage- User and session persistenceDrizzleEmailOTPStorage- OTP persistence
See src/lib/auth/storage.ts for the full implementation.
src/
├── app/ # Next.js app router pages
├── components/ # React components (SessionRefresh, UI)
└── lib/
├── auth/ # Auth configuration and storage
│ ├── auth.ts # Kenmon setup
│ ├── storage.ts # Drizzle storage implementations
│ ├── actions.ts # Server actions
│ └── utils.ts # Helper functions
├── db/ # Database setup and schema
└── config.ts # App configuration
To stop the PostgreSQL container:
docker-compose downTo stop and remove all data:
docker-compose down -v- kenmon - Core authentication service
- @kenmon/nextjs-adapter - Next.js adapter
- @kenmon/email-otp-authenticator - Email OTP authenticator