I want to build a node.js application with express but face this problem: when I try to login and my index.ejs sends a post request to my server I get a 4040 error. I am a programming novice and hope someone could help.
here ist my index.ejs
<!-- index.ejs -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mockup Kubernetes</title>
</head>
<body>
<h1>Fotodaten</h1>
<div id ="app" class ="container_img"></div>
<form action="/api/fotos" method="GET">
<table class="w3-table w3-striped w3-border" border="1">
<thead>
<tr>
<th>id</th>
<th>image_path</th>
<th>title</th>
</tr>
</thead>
<tbody>
<% fotoData.forEach(row => { %>
<tr>
<td><%= row.id %></td>
<td><%= row.image_path %></td>
<td><%= row.title %></td>
</tr>
<% }); %>
</tbody>
</table>
</form>
<div>
<div class="field">
<h1>Userdaten</h1>
<p>Hier befindet sich ein Ausschnitt zu den aktuell hochgeladenen Bildern.</p>
<h4>Alle registrierten User</h4>
</div>
<form action="auth/userdata" method="GET">
<table class="w3-table w3-striped w3-border" border="1">
<thead>
<tr>
<th>ID</th>
<th>Benutzername</th>
<th>Name</th>
<th>Nachname</th>
<th>E-Mail</th>
<th>Rolle</th>
</tr>
</thead>
<tbody>
<% userData.forEach(row => { %>
<tr>
<td><%= row.id %></td>
<td><%= row.username %></td>
<td><%= row.name %></td>
<td><%= row.surname %></td>
<td><%= row.email %></td>
<td><%= row.role %></td>
</tr>
<% }); %>
</tbody>
</table>
</table>
</form>
</div>
<div class="login_form">
<h1>Login</h1>
<form action="/auth/login" method="POST">
<div class="container">
<label for="usernameOrEmail">Benutzername oder E-Mail:</label>
<input type="text" id="usernameOrEmail" name="usernameOrEmail" required placeholder="Beliebigen Benutzernamen eingeben">
<label for="current-password">Passwort:</label>
<input type="password" id="current-password" name="password" autocomplete="current-password" required placeholder="Eingabe des Passworts">
<div class="button_login">
<button type="submit">ANMELDEN</button>
</div>
</div>
</form>
</div>
</body>
</html>
I created a webserver in index.js
const express = require('express');
const ejs = require('ejs');
const path = require('path');
const { idp, ensureAuthenticated, ensureAdmin, getAllUserData } = require('../idp/idp');
const app = express();
const port = process.env.PORT || 8000;
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
app.get('/', async (req, res) => {
try {
const userDataResponse = await fetch('http://localhost:3002/auth/userdata');
if (!userDataResponse.ok) {
throw new Error('Failed to fetch user data from backend');
}
const userData = await userDataResponse.json();
const fotoDataResponse = await fetch('http://localhost:3002/api/fotos');
if (!fotoDataResponse.ok) {
throw new Error('Failed to fetch foto data from backend');
}
const fotoData = await fotoDataResponse.json();
res.render('index', { userData, fotoData });
} catch (error) {
console.error('Error fetching data from backend:', error.message);
res.status(500).send('Internal Server Error');
}
});
idp.use((req, res, next) => {
console.log('Authentifizierungs-Middleware erreicht');
});
app.get('/admin', ensureAdmin, async (req, res) => {
try {
const allUserData = await getAllUserData();
res.render('admin', { data: allUserData });
} catch (error) {
console.error('Fehler beim Abrufen der Benutzerdaten für Admin-Seite:', error);
res.status(500).send('Interner Serverfehler');
}
});
app.get('/index', ensureAuthenticated, (req, res) => {
res.render('index', { });
});
app.listen(port, () => {
console.log(`Start Webserver auf http://localhost:${port}`);
});
and this is my idp:
const express = require('express');
const idp = express.Router();
const bcrypt = require('bcrypt');
const session = require('express-session');
const PgSession = require('connect-pg-simple')(session);
const { Pool } = require('pg');
const userConfig = require('./configs/configDB');
const pool = new Pool(userConfig);
//Create Session
idp.use(
session({
store: new PgSession({
pool,
tableName: 'sessions',
}),
secret: 'keyboard cat',
resave: false,
saveUninitialized: false,
})
);
const passport = require('passport');
const LocalStrategy = require('passport-local');
passport.use(new LocalStrategy(
{
usernameField: 'usernameOrEmail',
passwordField: 'password',
},
async (usernameOrEmail, password, done) => {
try {
const result = await pool.query('SELECT * FROM userdata WHERE username = $1 OR email = $1', [usernameOrEmail]);
if (result.rows.length === 0) {
return done(null, false, { message: 'Invalid username or email.' });
}
const user = result.rows[0];
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
console.log('Password does not match');
return done(null, false, { message: 'Invalid password.' });
}
const userDataInSession = {
id: user.id,
username: user.username,
role: user.role,
};
return done(null, userDataInSession);
} catch (err) {
return done(err);
}
}
));
//Middleware
const bodyParser = require('body-parser');
idp.use(bodyParser.urlencoded({ extended: true }));
idp.use(bodyParser.json());
idp.use(passport.initialize());
idp.use(passport.session());
idp.use(passport.authenticate('session'));
passport.serializeUser(function (user, cb) {
process.nextTick(function () {
console.log('Serialized User aus der Funktion:', user);
cb(null, { id: user.id, username: user.username, role: user.role });
});
});
passport.deserializeUser(function (user, cb) {
console.log('Deserialized User aus der Funktion:', user);
process.nextTick(function () {
cb(null, user);
});
});
idp.get('/userdata', async (req, res) => {
try {
const result = await pool.query('SELECT * FROM userdata');
const userData = result.rows;
res.json(userData);
} catch (error) {
console.error('Error fetching userdata from database:', error.message);
res.status(500).send('Internal Server Error');
}
});
idp.use((req, res, next) => {
if (req.isAuthenticated()) {
return next();
} else {
res.status(401).send('Unauthorized, sent from idp');
}
});
idp.post('/login/password', async (req, res, next) => {
try {
const result = await pool.query('SELECT * FROM userdata WHERE username = $1 OR email = $1', [req.body.usernameOrEmail]);
console.log('Anfrage erhalten:', req.body);
if (result.rows.length === 0) {
// Benutzername oder Passwort sind nicht korrekt
return res.status(401).render('index', { error: { details: "Benutzername oder Passwort sind nicht korrekt.", color: "warning" } });
}
const user = result.rows[0];
const passwordMatch = await bcrypt.compare(req.body.password, user.password);
console.log('Password Match:', passwordMatch);
if (passwordMatch) {
// Authentifizierung erfolgreich
req.session.passport = { user: user.id, username: user.username, role: user.role };
req.logIn(user, (err) => {
if (err) {
return next(err);
}
if (user.role === 'admin') {
console.log('Weiterleitung zu /admin für Admin:', user.username);
return res.redirect('/admin');
} else {
console.log('Weiterleitung zu /index für Benutzer:', user.username);
return res.redirect('/index');
}
});
} else {
// Passwort stimmt nicht überein
console.log('Passwort stimmt nicht überein für', user.username);
return res.status(401).render('index', { error: { details: "Benutzername oder Passwort sind nicht korrekt.", color: "warning" } });
}
} catch (error) {
console.error('Fehler:', error);
renderError(res, error);
}
});
function ensureAdmin(req, res, next) {
console.log('ensureAdmin Middleware erreicht');
console.log('User role:', req.user.role);
if (req.user.role === 'admin') {
return next();
} else {
console.log('Fehler bei der Überprüfung Adminrolle aufgetreten.');
console.log('User details:', req.user);
res.redirect('/index');
}
}
function ensureAuthenticated(req, res, next) {
console.log('ensureAuthenticated Middleware erreicht');
if (req.isAuthenticated()) {
return next();
}
res.redirect('/index');
}
async function getAllUserData() {
try {
const result = await pool.query('SELECT * FROM userdata');
return result.rows; // Gibt alle Benutzerdaten zurück
} catch (error) {
console.error('Fehler beim Abrufen aller Benutzerdaten aus der Datenbank:', error);
throw error;
}
}
async function getUserDataById(userId) {
try {
const result = await pool.query('SELECT * FROM userdata WHERE id = $1', [userId]);
return result.rows;
} catch (error) {
console.error('Fehler beim Abrufen von Benutzerdaten nach ID:', error);
throw error;
}
}
module.exports = {
idp,
ensureAdmin,
ensureAuthenticated,
getAllUserData,
getUserDataById
};
I have a server in front of the idp, which is at server.js
const express = require('express');
const { Pool } = require('pg');
const { idp, ensureAdmin, getAllUserData } = require('../idp/idp');
const { fotomanager, getAllFotoData } = require('../fotomanager/fotomanager');
const app = express();
const port = process.env.PORT || 3002;
//Middleware für das Parsen von JSON-Daten im Request-Body
app.use(express.json());
app.use('/auth', idp);
app.use('/api', fotomanager);
//Check Server
app.get("/", (req, res) => {
res.send("Willkommen auf meinem Server!");
});
// Starten Sie den Server
app.listen(port, () => {
console.log(`Server is now running on port ${port}`);
});
I tried the following:
- debugging and added some console.logs to get more information
- changed order of middleware
- put the post-route in the server.js to see if that helps, but it did not.
The first thing that comes to my mind is:
In your index.ejs file you have:
So you need to have a "/auth/login" route and use this route in your app.
But in your idp file, you have:
You need to adjust your form action to match the route. You can try:
Edit: Another problem that I found is that you are using two different servers, and the POST request is going to the web server that doesn't have the auth endpoint.
You can try this if the auth server is running on port 3002:
One thing for sure, when you get a 404 result it's basically saying that the endpoint doesn't exist.