January 30, 2025

UPDATED February 13, 2025

Setting up jwt authentication, routes and a postgres connection

how to connect an express application to postgres and setup jwt authentication
Setting up jwt authentication, routes and a postgres connection
Step 1: Project Setup

1. Initialize a Node.js project and install dependencies:

bash
npm init -y
npm install prisma @prisma/client bcrypt jsonwebtoken dotenv express
npm install -D typescript ts-node @types/express @types/node @types/bcrypt @types/jsonwebtoken

1. Create a .env file for environment variables:

bash
DATABASE_URL="postgresql://USER:PASSWORD@localhost:5432/DB_NAME?schema=public"
JWT_SECRET="your_jwt_secret_key"
Generating a JWT Secret

you can generate a secure JWT secret using one of the following methods:

  • Using Node.js Crypto Module
  • bash
    node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

    b. Using Online Tools

    You can use online tools like: - RandomKeygen - UUID Generator

    c. Using OpenSSL

    bash
    openssl rand -hex 32
    Step 2: Configure Prisma

    1. Initialize Prisma and create the User model in prisma/schema.prisma:

    bash
    // prisma/schema.prisma
    generator client {
    provider = "prisma-client-js"
    }
    datasource db {
    provider = "postgresql"
    url = env("DATABASE_URL")
    }
    model User {
    id Int @id @default(autoincrement())
    email String @unique
    password String
    name String?
    }

    2. Run migrations to create the database tables:

    bash
    npx prisma migrate dev --name init
    Step 3: Create Utility Functions

    Password Hashing (using bcrypt):

    JWT Token Generation (using jsonwebtoken):

    javascript
    import bcrypt from "bcrypt";
    import jwt from "jsonwebtoken";
    const saltRounds = 10;
    // Hash password
    export const hashPassword = async (password) => {
    return await bcrypt.hash(password, saltRounds);
    };
    // Compare password
    export const comparePassword = async (password, hash) => {
    return await bcrypt.compare(password, hash);
    };
    // Generate JWT token
    export const generateToken = (userId) => {
    return jwt.sign({ userId }, process.env.JWT_SECRET, { expiresIn: "1h" });
    };
    // // Verify a token
    export const validateToken = (req, res, next) => {
    const token = req.headers.authorization?.split(" ")[1];
    if (!token) return res.status(401).json({ error: "Unauthorized" });
    try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = decoded;
    next();
    } catch (error) {
    res.status(401).json({ error: "Invalid token" });
    }
    };
    Step 4: Implement Authentication Routes
    javascript
    import express from 'express';
    import { PrismaClient } from '@prisma/client';
    import { hashPassword, comparePassword, generateToken } from './utils/auth';
    const prisma = new PrismaClient();
    const app = express();
    app.use(express.json());
    // Register a new user
    app.post('/register', async (req, res) => {
    const { email, password, name } = req.body;
    try {
    const hashedPassword = await hashPassword(password);
    const user = await prisma.user.create({
    data: {
    email,
    password: hashedPassword,
    name,
    },
    });
    res.status(201).json({ id: user.id, email: user.email });
    } catch (error) {
    res.status(400).json({ error: 'User already exists' });
    }
    });
    // Login
    app.post('/login', async (req, res) => {
    const { email, password } = req.body;
    const user = await prisma.user.findUnique({ where: { email } });
    if (!user) return res.status(404).json({ error: 'User not found' });
    const isValid = await comparePassword(password, user.password);
    if (!isValid) return res.status(401).json({ error: 'Invalid password' });
    const token = generateToken(user.id);
    res.json({ token });
    });
    const PORT = 3000;
    app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
    Running the application

    node index.js

    for MVC routing architecture look at my github repository where you can clone and run with configured routes and best practices

    Learn postgres

    then cd postgres30-01

    Key Security Practices
  • Password Hashing: Never store plain-text passwords (we used bcrypt).
  • JWT Expiry: Tokens expire after 1h (adjust in generateToken).
  • Environment Variables: Keep secrets like JWT_SECRET and DATABASE_URL in .env.
  • HTTPS: Always use HTTPS in production.
  • Input Validation: Add validation for email/password (e.g., with Zod).
  • Latest Articles

    More Articles

    Creating a server in node(Express)

    creating servers using express

    November 7, 2024

    Intergrating a simulator ecommerce site with mysql, redis

    February 13, 2025
    How can I help you architect your next project?

    Njenga AI

    System Assistant

    👋 Hi! I'm Njenga, Kenneth's AI assistant. How can I help you today?