Below is a production-style Auth Service for your Local Marketplace Microservices Platform using:
- Node.js
- Express
- PostgreSQL
- Prisma ORM
- JWT Authentication
- Docker-ready structure
- Layered architecture (Controller → Service → Repository)
This structure is similar to what engineers use in production systems at companies like Stripe and Shopify.
📁 Auth Service Folder Structure
auth-service
│
├── src
│ ├── config
│ │ └── db.js
│ │
│ ├── controllers
│ │ └── auth.controller.js
│ │
│ ├── services
│ │ └── auth.service.js
│ │
│ ├── repositories
│ │ └── user.repository.js
│ │
│ ├── routes
│ │ └── auth.routes.js
│ │
│ ├── middlewares
│ │ └── auth.middleware.js
│ │
│ ├── utils
│ │ ├── hash.js
│ │ └── jwt.js
│ │
│ ├── app.js
│ └── server.js
│
├── prisma
│ ├── schema.prisma
│ └── seed.js
│
├── .env
├── package.json
└── Dockerfile
1️⃣ package.json
{
"name": "auth-service",
"version": "1.0.0",
"main": "src/server.js",
"scripts": {
"dev": "nodemon src/server.js",
"start": "node src/server.js",
"prisma": "prisma migrate dev"
},
"dependencies": {
"@prisma/client": "^5.0.0",
"bcryptjs": "^2.4.3",
"dotenv": "^16.0.0",
"express": "^4.18.2",
"jsonwebtoken": "^9.0.0"
},
"devDependencies": {
"nodemon": "^3.0.0",
"prisma": "^5.0.0"
}
}
2️⃣ .env
PORT=4000
DATABASE_URL="postgresql://postgres:password@localhost:5432/auth_db"
JWT_SECRET=supersecret
3️⃣ Prisma Schema
📁 prisma/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id String @id @default(uuid())
name String
email String @unique
password String
role String @default("CUSTOMER")
createdAt DateTime @default(now())
}
Run:
npx prisma generate
npx prisma migrate dev --name init
4️⃣ DB Config
📁 src/config/db.js
const { PrismaClient } = require('@prisma/client')
const prisma = new PrismaClient()
module.exports = prisma
5️⃣ Hash Utility
📁 src/utils/hash.js
const bcrypt = require('bcryptjs')
exports.hashPassword = async (password) => {
return bcrypt.hash(password, 10)
}
exports.comparePassword = async (password, hash) => {
return bcrypt.compare(password, hash)
}
6️⃣ JWT Utility
📁 src/utils/jwt.js
const jwt = require('jsonwebtoken')
exports.generateToken = (payload) => {
return jwt.sign(payload, process.env.JWT_SECRET, {
expiresIn: "1d"
})
}
7️⃣ Repository Layer
📁 src/repositories/user.repository.js
const prisma = require('../config/db')
exports.createUser = (data) => {
return prisma.user.create({ data })
}
exports.findUserByEmail = (email) => {
return prisma.user.findUnique({
where: { email }
})
}
8️⃣ Service Layer
📁 src/services/auth.service.js
const userRepo = require('../repositories/user.repository')
const { hashPassword, comparePassword } = require('../utils/hash')
const { generateToken } = require('../utils/jwt')
exports.register = async (data) => {
const existingUser = await userRepo.findUserByEmail(data.email)
if (existingUser) {
throw new Error("User already exists")
}
const hashedPassword = await hashPassword(data.password)
const user = await userRepo.createUser({
...data,
password: hashedPassword
})
return user
}
exports.login = async ({ email, password }) => {
const user = await userRepo.findUserByEmail(email)
if (!user) {
throw new Error("Invalid credentials")
}
const valid = await comparePassword(password, user.password)
if (!valid) {
throw new Error("Invalid credentials")
}
const token = generateToken({
id: user.id,
email: user.email
})
return { token }
}
9️⃣ Controller
📁 src/controllers/auth.controller.js
const authService = require('../services/auth.service')
exports.register = async (req, res) => {
try {
const user = await authService.register(req.body)
res.status(201).json(user)
} catch (error) {
res.status(400).json({
message: error.message
})
}
}
exports.login = async (req, res) => {
try {
const result = await authService.login(req.body)
res.json(result)
} catch (error) {
res.status(401).json({
message: error.message
})
}
}
🔟 Routes
📁 src/routes/auth.routes.js
const express = require('express')
const router = express.Router()
const authController = require('../controllers/auth.controller')
router.post('/register', authController.register)
router.post('/login', authController.login)
module.exports = router
1️⃣1️⃣ Express App
📁 src/app.js
const express = require('express')
const authRoutes = require('./routes/auth.routes')
const app = express()
app.use(express.json())
app.use('/auth', authRoutes)
module.exports = app
1️⃣2️⃣ Server
📁 src/server.js
require('dotenv').config()
const app = require('./app')
const PORT = process.env.PORT || 4000
app.listen(PORT, () => {
console.log(`Auth service running on port ${PORT}`)
})
1️⃣3️⃣ Dockerfile
FROM node:20
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 4000
CMD ["npm","start"]
🚀 API Endpoints
Register User
POST /auth/register
Body
{
"name": "John",
"email": "john@example.com",
"password": "123456"
}
Login
POST /auth/login
Body
{
"email": "john@example.com",
"password": "123456"
}
⭐ What Makes This Production-Ready
✔ Layered architecture
✔ Repository pattern
✔ Prisma ORM
✔ JWT authentication
✔ Microservice-ready
✔ Docker-ready
✔ Scalable structure
Top comments (0)