I'm building a blob web application using Express.js where users can log in and access protected routes. I've set up session management using express-session and authentication with passport-local. However, when I try to access the /home route after logging in, I'm consistently getting a "401 Unauthorized" error. It might briefly open for like 1-2 sec and then direct me to /login.
import express from 'express';
import bodyParser from 'body-parser';
import cors from 'cors';
import pg from 'pg';
import { fileURLToPath } from 'url';
import path from 'path';
import bcrypt from 'bcrypt';
import passport from 'passport';
import { Strategy } from 'passport-local';
import session from 'express-session';
import dotenv from 'dotenv';
dotenv.config();
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
let { PGHOST, PGDATABASE, PGUSER, PGPASSWORD, ENDPOINT_ID } = process.env;
PGPASSWORD = decodeURIComponent(PGPASSWORD);
const pool = new pg.Pool({
user: PGUSER,
host: PGHOST,
database: PGDATABASE,
password: PGPASSWORD,
port: 5432,
ssl: {
rejectUnauthorized: false,
},
connectionTimeoutMillis: 3000,
});
const app = express();
const PORT = process.env.PORT || 5000;
const saltRounds = 10;
app.use(cors({
origin: 'https://blog-t7q7.onrender.com',
credentials: true
}));
app.use(bodyParser.json({ limit: '50mb' }));
app.use(bodyParser.urlencoded({ limit: '50mb', extended: true }));
app.use(session({
secret: 'TOPSECRETWORD',
resave: false,
saveUninitialized: false,
cookie: {
secure: true,
sameSite: 'none',
httpOnly: true,
}
}));
app.use(passport.initialize());
app.use(passport.session());
const isAuthenticated = (req, res, next) => {
if (res.isAuthenticated()) {
return next();
} else {
res.status(401).json({ error: 'Unauthorized' });
}
};
app.get("/home", isAuthenticated, async (req, res) => {
try {
const result = await pool.query('SELECT post_title, post_content FROM userposts');
res.status(200).json(result.rows);
} catch (error) {
console.error('Error fetching posts:', error);
res.status(500).json({ error: 'Internal Server Error' });
}
});
app.post("/register", async (req, res) => {
const { username, userpassword } = req.body;
try {
const userCheckResult = await pool.query('SELECT * FROM blog WHERE username = $1', [username]);
if (userCheckResult.rows.length > 0) {
return res.status(400).send({ error: "Username already taken" });
}
const hashedPassword = await bcrypt.hash(userpassword, saltRounds);
const result = await pool.query('INSERT INTO blog (username, userpassword) VALUES ($1, $2) RETURNING *', [username, hashedPassword]);
const user = result.rows[0];
req.login(user, (err) => {
if (err) {
console.log(err);
res.status(500).send({ error: "Registration failed" });
} else {
res.status(200).send({ message: "User registered successfully" });
}
});
} catch (error) {
console.error("Error inserting user:", error);
res.status(500).send({ error: "Registration failed" });
}
});
app.post("/login", (req, res, next) => {
passport.authenticate("local", (err, user, info) => {
if (err) {
console.error('Error during authentication:', err);
return res.status(500).send({ error: "Internal Server Error" });
}
if (!user) {
console.log('Authentication failed:', info);
return res.status(401).send({ error: "Invalid username or password" });
}
req.logIn(user, (err) => {
if (err) {
console.error('Error logging in user:', err);
return res.status(500).send({ error: "Internal Server Error" });
}
return res.status(200).send({ message: "User logged in successfully" });
});
})(req, res, next);
});
app.post("/postblog", isAuthenticated, async (req, res) => {
const { postTitle, postContent } = req.body;
try {
await pool.query('INSERT INTO userposts (post_title, post_content) VALUES ($1, $2)', [postTitle, postContent]);
res.status(200).send({ message: "Post inserted successfully" });
} catch (error) {
console.error("Error inserting post:", error);
res.status(500).send({ error: "Error inserting post" });
}
});
app.post("/post", isAuthenticated, async (req, res) => {
const { postTitle } = req.body;
console.log('Received request to fetch post:', postTitle);
try {
const result = await pool.query('SELECT * FROM userposts WHERE post_title = $1', [postTitle]);
console.log('Query result:', result.rows);
if (result.rows.length > 0) {
const post = result.rows[0];
res.status(200).send({ post });
} else {
res.status(404).send({ error: "Post not found" });
}
} catch (error) {
console.error("Error fetching post:", error);
res.status(500).send({ error: "Error fetching post" });
}
});
passport.use(new Strategy(
{
usernameField: 'username',
passwordField: 'userpassword'
},
async (username, password, cb) => {
try {
const result = await pool.query('SELECT * FROM blog WHERE username = $1', [username]);
if (result.rows.length > 0) {
const user = result.rows[0];
const storedHashedPassword = user.userpassword;
bcrypt.compare(password, storedHashedPassword, (err, isMatch) => {
if (err) {
return cb(err);
}
if (isMatch) {
return cb(null, user);
} else {
return cb(null, false, { message: 'Incorrect username or password.' });
}
});
} else {
return cb(null, false, { message: 'Incorrect username or password.' });
}
} catch (error) {
console.error("Error logging in user:", error);
return cb(error);
}
}
));
passport.serializeUser((user, cb) => {
cb(null, user.id);
});
passport.deserializeUser(async (id, cb) => {
try {
const result = await pool.query('SELECT * FROM blog WHERE id = $1', [id]);
if (result.rows.length > 0) {
cb(null, result.rows[0]);
} else {
cb(new Error('User not found'));
}
} catch (error) {
cb(error);
}
});
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
this is my index.js
import React, { useState } from "react";
import axios from 'axios';
import { useNavigate } from 'react-router-dom';
import './Login.css'; // Import the CSS file
function Login() {
const [name, setName] = useState("");
const [password, setPassword] = useState("");
const navigate = useNavigate();
const handleNameChange = (event) => {
setName(event.target.value);
}
const handlePasswordChange = (event) => {
setPassword(event.target.value);
}
const loginUser = async (event) => {
event.preventDefault();
try {
const response = await axios.post('https://blog-backend-khj7.onrender.com/login',
{ username: name, userpassword: password },
{ withCredentials: true });
if (response.status === 200) {
navigate('/home');
}
} catch (error) {
if (error.response) {
if (error.response.status === 400 || error.response.status === 401) {
alert("Invalid username or password");
} else {
console.error('Error logging in user:', error);
alert("There was an error logging in the user");
}
} else {
console.error('Error logging in user:', error);
alert("There was an error logging in the user");
}
}
}
return (
<div className="login-background">
<div className="login-container">
<h1>Login</h1>
<form onSubmit={loginUser}>
<input type="text" onChange={handleNameChange} name="username" value={name} placeholder="Username" required />
<input type="password" onChange={handlePasswordChange} name="userpassword" value={password} placeholder="Password" required />
<button type="submit">Submit</button>
</form>
</div>
</div>
);
}
export default Login;
login.jsx
import React, { useState } from "react";
import axios from 'axios';
import { useNavigate } from 'react-router-dom';
import './Register.css'; // Import the CSS file
function Register() {
const [name, setName] = useState("");
const [password, setPassword] = useState("");
const navigate = useNavigate();
function handleNameChange(event) {
setName(event.target.value);
}
function handlePasswordChange(event) {
setPassword(event.target.value);
}
async function registerUser(event) {
event.preventDefault();
try {
const response = await axios.post('https://blog-backend-khj7.onrender.com/register',
{ username: name, userpassword: password },
{ withCredentials: true }
);
if (response.status === 200) {
navigate('/home');
}
} catch (error) {
if (error.response && error.response.status === 400) {
alert("Username already exists");
} else {
console.error('There was an error registering the user:', error);
}
}
}
function goToLogin() {
navigate('/login');
}
return (
<div className="register-background">
<h1 className="register-header">Welcome to blog</h1>
<div className="register-container">
<h1>Register</h1>
<form onSubmit={registerUser}>
<input type="text" onChange={handleNameChange} value={name} placeholder="Username" />
<input type="password" onChange={handlePasswordChange} value={password} placeholder="Password" />
<button type="submit">Submit</button>
</form>
</div>
<h3>Already registered?</h3>
<h4 onClick={goToLogin} className="blog-go-login">Login</h4>
</div>
);
}
export default Register;
register.jsx
The site is live!You can also check https://blog-t7q7.onrender.com/
github https://github.com/AMEYSATI/Blog
The thing is in developer tools when i login correctly the cookie session is passed but i guess it do not get received /home or whatever
Please help me since this is also new to me