0% found this document useful (0 votes)
4 views16 pages

Auth Using PERN

The PERN Auth Guide provides a step-by-step tutorial on building a Login and Signup system using the PERN stack (PostgreSQL, Express.js, React, Node.js). It covers setting up the development environment, creating the project structure, writing backend code for user authentication, and building a React frontend for user interaction. The guide is designed for beginners and explains each step in simple terms with examples.

Uploaded by

k6875372
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views16 pages

Auth Using PERN

The PERN Auth Guide provides a step-by-step tutorial on building a Login and Signup system using the PERN stack (PostgreSQL, Express.js, React, Node.js). It covers setting up the development environment, creating the project structure, writing backend code for user authentication, and building a React frontend for user interaction. The guide is designed for beginners and explains each step in simple terms with examples.

Uploaded by

k6875372
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

PERN Auth Guide | © @devarthastudio

PERN Stack
Authentication System
A Beginner-Friendly Step-by-Step Guide

Stack Used
PostgreSQL • [Link] • React • [Link]

© 2025 @devarthastudio
All rights reserved. Unauthorized reproduction prohibited.

Page 1
PERN Auth Guide | © @devarthastudio

What Is This Guide About?


This guide will teach you, step-by-step, how to build a Login & Signup system using the PERN
stack. If you've never written a single line of code — don't worry. Every step is explained in plain
English with examples.

🎯 What You'll Build: A full-stack web app where users can Sign Up, Log In, and access a
protected page — all with passwords stored safely.

What is PERN?
PERN is just a fancy word for 4 tools that work together to build web apps:

Letter Stands For What It Does (Simple Words)

P PostgreSQL The database — stores all your user info (like a super-smart
Excel sheet)

E [Link] The backend server — handles requests from the browser (like a
restaurant waiter)

R React The frontend — what the user sees on screen (buttons, forms,
pages)

N [Link] Runs JavaScript on the server — powers [Link] behind the


scenes

Part 1 — Setting Up Your Computer


Before writing any code, you need to install a few free tools. Think of this like getting your art
supplies before painting.

1 Install [Link]

1. Open your browser and go to: [Link]


2. Download the LTS version (the green button — it says 'Recommended')
3. Run the installer and click Next until it finishes
4. To check if it worked, open your Terminal (Mac) or Command Prompt (Windows) and type:

node -v
npm -v

Page 2
PERN Auth Guide | © @devarthastudio

✅ Success: You should see version numbers like v20.x.x — that means [Link] is
installed!

2 Install PostgreSQL

5. Go to: [Link]
6. Choose your operating system (Windows / Mac)
7. Download and install. During setup, set a password — remember it! (Example:
mypassword123)
8. Also install pgAdmin (it usually comes with PostgreSQL) — this is a visual tool to see your
database

📝 Write It Down: Your PostgreSQL password is very important. Write it somewhere safe.
You'll need it later.

3 Install VS Code (Code Editor)

9. Go to: [Link]
10. Download and install — it's free!
11. This is where you'll write all your code. Think of it as Microsoft Word, but for code.

Part 2 — Creating the Project


Now let's create the folder structure for our app. Our project will have two main parts:

• server — This is the backend (Express + [Link] + PostgreSQL)


• client — This is the frontend (React)

4 Create the Project Folders

Open your Terminal or Command Prompt and type these commands one by one:

mkdir pern-auth
cd pern-auth
mkdir server
mkdir client

Page 3
PERN Auth Guide | © @devarthastudio

💡 What just happened: mkdir creates a new folder. cd means 'change directory' — it
moves you into that folder.

5 Set Up the Backend (Server)

Type these commands to enter the server folder and set it up:

cd server
npm init -y
npm install express pg bcrypt jsonwebtoken dotenv cors

Here's what each package does:

Package What It Does

express Creates the server — handles routes like /login and /register
pg Connects [Link] to PostgreSQL database
bcrypt Scrambles passwords so they're stored safely (hashing)
jsonwebtoken Creates a 'token' — like a VIP pass — that proves you're logged in
dotenv Loads secret values (like passwords) from a .env file
cors Allows the React frontend to talk to the Express backend

Part 3 — Setting Up the Database


Now let's create the database where we'll store user accounts.

6 Create the Database in pgAdmin

12. Open pgAdmin (search it in your Start Menu or Applications)


13. Login with the password you set during PostgreSQL install
14. Right-click on Databases → Create → Database
15. Name it: pern_auth_db → Click Save

7 Create the Users Table

In pgAdmin, click on pern_auth_db → go to the Query Tool (the little SQL icon) and run this:

Page 4
PERN Auth Guide | © @devarthastudio

CREATE TABLE users (


id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(150) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);

Breaking it down in plain English:

• id — auto-number for each user (1, 2, 3...)


• name — user's full name
• email — must be unique (no two users with the same email)
• password — will store the scrambled (hashed) password
• created_at — automatically records when the account was made

Part 4 — Writing the Backend Code


Now we write the actual server code. Open VS Code, open your server folder.

8 Create the .env File

Inside the server folder, create a new file called .env (just that name, nothing else). This file holds
your secrets:

DB_USER=postgres
DB_HOST=localhost
DB_NAME=pern_auth_db
DB_PASSWORD=yourpassword123
DB_PORT=5432
JWT_SECRET=mysupersecretkey_changethis
PORT=5000

⚠️ Important: Replace yourpassword123 with your actual PostgreSQL password. Never


share this file with anyone!

9 Create the Database Connection File

Create a file: server/[Link]

Page 5
PERN Auth Guide | © @devarthastudio

// [Link] — connects our app to PostgreSQL


const { Pool } = require("pg");
require("dotenv").config();

const pool = new Pool({


user: [Link].DB_USER,
host: [Link].DB_HOST,
database: [Link].DB_NAME,
password: [Link].DB_PASSWORD,
port: [Link].DB_PORT,
});

[Link] = pool;

💡 What is this: Pool is a connection manager. Think of it as a phone line between your app
and the database.

10 Create the Main Server File

Create a file: server/[Link]

// [Link] — the main server entry point


const express = require("express");
const cors = require("cors");
require("dotenv").config();

const app = express();

// Middleware
[Link](cors());
[Link]([Link]()); // allows reading JSON from requests

// Routes
[Link]("/api/auth", require("./routes/auth"));

const PORT = [Link] || 5000;


[Link](PORT, () => {
[Link](`Server running on port ${PORT}`);
});

11 Create Auth Routes

Page 6
PERN Auth Guide | © @devarthastudio

Create a folder: server/routes — then create server/routes/[Link]

// routes/[Link] — handles /register and /login


const express = require("express");
const bcrypt = require("bcrypt");
const jwt = require("jsonwebtoken");
const pool = require("../db");
const router = [Link]();

// ─── REGISTER ──────────────────────────────────────────


[Link]("/register", async (req, res) => {
try {
const { name, email, password } = [Link];

// Check if user already exists


const exists = await [Link](
"SELECT * FROM users WHERE email = $1", [email]
);
if ([Link] > 0) {
return [Link](400).json({ message: "Email already registered" });
}

// Hash (scramble) the password — never store plain text!


const saltRounds = 10;
const hashedPassword = await [Link](password, saltRounds);

// Save user to database


const newUser = await [Link](
"INSERT INTO users (name, email, password) VALUES ($1, $2, $3)
RETURNING id, name, email",
[name, email, hashedPassword]
);

[Link](201).json({ message: "User created!", user:


[Link][0] });
} catch (err) {
[Link](err);
[Link](500).json({ message: "Server error" });
}
});

// ─── LOGIN ─────────────────────────────────────────────


[Link]("/login", async (req, res) => {
try {
const { email, password } = [Link];

Page 7
PERN Auth Guide | © @devarthastudio

// Find user by email


const userResult = await [Link](
"SELECT * FROM users WHERE email = $1", [email]
);
if ([Link] === 0) {
return [Link](400).json({ message: "Invalid credentials" });
}

const user = [Link][0];

// Compare entered password with hashed password


const isMatch = await [Link](password, [Link]);
if (!isMatch) {
return [Link](400).json({ message: "Invalid credentials" });
}

// Create a JWT token (VIP pass)


const token = [Link](
{ id: [Link], email: [Link] },
[Link].JWT_SECRET,
{ expiresIn: "1h" }
);

[Link]({ message: "Login successful!", token, name: [Link] });


} catch (err) {
[Link](err);
[Link](500).json({ message: "Server error" });
}
});

[Link] = router;

🔐 How Security Works Here: The password is hashed using bcrypt (one-way scramble).
Even if someone steals your database, they can't read the passwords. JWT gives the user a
token after login — like a key card.

12 Create Middleware to Protect Routes

Create: server/middleware/[Link] — This checks if a user is logged in before allowing them access.

// middleware/[Link]
const jwt = require("jsonwebtoken");

Page 8
PERN Auth Guide | © @devarthastudio

require("dotenv").config();

[Link] = (req, res, next) => {


const authHeader = [Link]["authorization"];
const token = authHeader && [Link](" ")[1]; // format: Bearer
TOKEN

if (!token) {
return [Link](401).json({ message: "No token. Access denied." });
}

try {
const decoded = [Link](token, [Link].JWT_SECRET);
[Link] = decoded; // attach user info to request
next(); // move to the next step
} catch (err) {
[Link](403).json({ message: "Invalid or expired token." });
}
};

Now create: server/routes/[Link] — a route only logged-in users can access:

// routes/[Link]
const express = require("express");
const authMiddleware = require("../middleware/auth");
const router = [Link]();

[Link]("/dashboard", authMiddleware, (req, res) => {


[Link]({ message: `Welcome back, user ${[Link]}!` });
});

[Link] = router;

Also add this line to [Link] (just below the auth route):

[Link]("/api/protected", require("./routes/protected"));

Part 5 — Building the React Frontend


Now let's create the part users actually see! Go back to the main pern-auth folder in your terminal.

13 Create the React App

Page 9
PERN Auth Guide | © @devarthastudio

cd ../client
npm create vite@latest . -- --template react
npm install
npm install axios react-router-dom

💡 What is Axios: Axios is a tool that lets React send requests to your Express server —
like a messenger between frontend and backend.

14 Create the Signup Page

Create: client/src/pages/[Link]

// [Link]
import { useState } from "react";
import axios from "axios";
import { useNavigate } from "react-router-dom";

export default function Signup() {


const [form, setForm] = useState({ name: "", email: "", password: "" });
const [msg, setMsg] = useState("");
const navigate = useNavigate();

const handleChange = (e) => {


setForm({ ...form, [[Link]]: [Link] });
};

const handleSubmit = async (e) => {


[Link]();
try {
const res = await
[Link]("[Link] form);
setMsg([Link]);
navigate("/login"); // redirect to login after signup
} catch (err) {
setMsg([Link]?.data?.message || "Something went wrong");
}
};

return (
<div style={{ maxWidth: 400, margin: "80px auto", padding: 24 }}>
<h2>Create an Account</h2>
{msg && <p style={{ color: "red" }}>{msg}</p>}
<form onSubmit={handleSubmit}>

Page 10
PERN Auth Guide | © @devarthastudio

<input name="name" placeholder="Full Name"


onChange={handleChange} required /><br/>
<input name="email" placeholder="Email"
onChange={handleChange} required /><br/>
<input name="password" placeholder="Password" type="password"
onChange={handleChange} required /><br/>
<button type="submit">Sign Up</button>
</form>
</div>
);
}

15 Create the Login Page

Create: client/src/pages/[Link]

// [Link]
import { useState } from "react";
import axios from "axios";
import { useNavigate } from "react-router-dom";

export default function Login() {


const [form, setForm] = useState({ email: "", password: "" });
const [msg, setMsg] = useState("");
const navigate = useNavigate();

const handleChange = (e) => {


setForm({ ...form, [[Link]]: [Link] });
};

const handleSubmit = async (e) => {


[Link]();
try {
const res = await [Link]("[Link]
form);
[Link]("token", [Link]); // save the VIP pass
[Link]("name", [Link]);
navigate("/dashboard"); // go to protected page
} catch (err) {
setMsg([Link]?.data?.message || "Something went wrong");
}
};

return (
<div style={{ maxWidth: 400, margin: "80px auto", padding: 24 }}>

Page 11
PERN Auth Guide | © @devarthastudio

<h2>Login</h2>
{msg && <p style={{ color: "red" }}>{msg}</p>}
<form onSubmit={handleSubmit}>
<input name="email" placeholder="Email"
onChange={handleChange} required /><br/>
<input name="password" placeholder="Password" type="password"
onChange={handleChange} required /><br/>
<button type="submit">Login</button>
</form>
</div>
);
}

16 Create the Dashboard (Protected Page)

Create: client/src/pages/[Link] — Only accessible after login.

// [Link]
import { useEffect, useState } from "react";
import axios from "axios";
import { useNavigate } from "react-router-dom";

export default function Dashboard() {


const [message, setMessage] = useState("");
const name = [Link]("name");
const navigate = useNavigate();

useEffect(() => {
const fetchData = async () => {
try {
const token = [Link]("token");
const res = await [Link](
"[Link]
{ headers: { Authorization: `Bearer ${token}` } }
);
setMessage([Link]);
} catch (err) {
navigate("/login"); // not logged in? send them back
}
};
fetchData();
}, []);

const logout = () => {


[Link]("token");

Page 12
PERN Auth Guide | © @devarthastudio

[Link]("name");
navigate("/login");
};

return (
<div style={{ maxWidth: 600, margin: "80px auto", padding: 24 }}>
<h2>Dashboard</h2>
<p>Hello, {name}! You are logged in.</p>
<p>{message}</p>
<button onClick={logout}>Logout</button>
</div>
);
}

17 Set Up React Router (Navigation)

Replace everything in client/src/[Link] with this:

// [Link]
import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom";
import Signup from "./pages/Signup";
import Login from "./pages/Login";
import Dashboard from "./pages/Dashboard";

export default function App() {


return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Navigate to="/login" />} />
<Route path="/signup" element={<Signup />} />
<Route path="/login" element={<Login />} />
<Route path="/dashboard" element={<Dashboard />} />
</Routes>
</BrowserRouter>
);
}

Part 6 — Running Your App


Almost there! Now let's start both the server and the React app.

18 Start the Backend Server

Page 13
PERN Auth Guide | © @devarthastudio

Open a Terminal window, go to the server folder, and run:

cd pern-auth/server
node [Link]

✅ Expected Output: Server running on port 5000 — this means your backend is live!

19 Start the React Frontend

Open a SECOND Terminal window (don't close the first one), go to the client folder:

cd pern-auth/client
npm run dev

🌐 Open Your Browser: Go to [Link] — you should see your app!

Test the app like this:

16. Go to /signup → Fill in your name, email, password → Click Sign Up


17. You'll be redirected to /login → Enter the same email + password → Click Login
18. You'll land on the /dashboard page — you are now authenticated!
19. Click Logout → You'll be sent back to /login

Part 7 — Final Folder Structure


Here is what your complete project should look like:

pern-auth/
├── server/
│ ├── middleware/
│ │ └── [Link] ← JWT check middleware
│ ├── routes/
│ │ ├── [Link] ← /register and /login
│ │ └── [Link] ← /dashboard (protected)
│ ├── [Link] ← PostgreSQL connection
│ ├── [Link] ← Main server file
│ └── .env ← Secret keys (never share!)

└── client/

Page 14
PERN Auth Guide | © @devarthastudio

└── src/
├── pages/
│ ├── [Link]
│ ├── [Link]
│ └── [Link]
└── [Link] ← Routes setup

Part 8 — How It All Works Together


Here's the full flow in plain English:

1 User fills the Signup form in React and clicks Submit

2 React sends the data (name, email, password) to Express server at POST
/api/auth/register

3 Express checks if the email exists in PostgreSQL. If yes → error. If no → continue.

4 bcrypt scrambles the password (e.g. mypassword → $2b$10$xyz...) and saves the user
to the database

5 User now goes to Login. React sends email + password to POST /api/auth/login

6 Express finds the user in the database, compares the password using bcrypt

7 If password matches, Express creates a JWT token and sends it back to React

8 React stores the token in localStorage. Future requests include this token in the headers

9 When accessing /dashboard, React sends the token to Express. Middleware checks it —
if valid, access granted!

Part 9 — Common Errors & Fixes

Error What To Do

Cannot connect to database Check your .env file — make sure DB_PASSWORD
matches what you set in PostgreSQL

CORS error in browser Make sure [Link](cors()) is in [Link] before your routes

Token is not defined You forgot to login first, or the token expired (1 hour limit).
Log in again.

Port 5000 already in use Change PORT=5000 to PORT=5001 in .env and update
axios URLs in React

Page 15
PERN Auth Guide | © @devarthastudio

Module not found error You forgot to run npm install in that folder. Go to the folder
and run it.

Password is correct but login fails Make sure you're using [Link]() — never
compare plain passwords directly

Part 10 — What's Next?


Congrats! You've built a full authentication system from scratch. Here's what you can add next:

• Email verification — send a confirmation email when someone signs up


• Forgot Password — let users reset their password via email link
• Refresh Tokens — JWT tokens that auto-renew so users stay logged in longer
• Role-Based Access — admins see different pages than regular users
• Rate Limiting — prevent bots from trying 1000 passwords per second
• React Context API — manage the auth state globally instead of localStorage

🚀 Keep Going: Every big web app you use — Instagram, YouTube, Amazon — has an
auth system like this at its core. You just built the same thing!

© 2025 @devarthastudio — All Rights Reserved


This document is the intellectual property of @devarthastudio.
Unauthorized reproduction, redistribution, or resale is strictly prohibited.

Page 16

You might also like