Files
ToDo-App_Node.js_Test/routes/authRoutes.js
2025-04-06 15:27:27 +02:00

134 lines
4.4 KiB
JavaScript

// routes/authRoutes.js
// Handles user registration, login, logout, and status check
const express = require('express');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const db = require('../db'); // Import database query function
require('dotenv').config();
const router = express.Router();
const JWT_SECRET = process.env.JWT_SECRET;
const JWT_EXPIRES_IN = process.env.JWT_EXPIRES_IN || '1h';
const SALT_ROUNDS = 10; // Cost factor for bcrypt hashing
// POST /api/auth/register - User Registration
router.post('/register', async (req, res) => {
const { username, password } = req.body;
// Basic validation
if (!username || !password) {
return res.status(400).json({ message: 'Benutzername und Passwort sind erforderlich.' });
}
try {
// Check if user already exists
const userCheck = await db.query('SELECT * FROM users WHERE username = $1', [username]);
if (userCheck.rows.length > 0) {
return res.status(409).json({ message: 'Benutzername bereits vergeben.' }); // 409 Conflict
}
// Hash the password
const passwordHash = await bcrypt.hash(password, SALT_ROUNDS);
// Insert new user into the database
const newUser = await db.query(
'INSERT INTO users (username, password_hash) VALUES ($1, $2) RETURNING id, username',
[username, passwordHash]
);
console.log(`User registered: ${newUser.rows[0].username}`);
// Respond with success message (or automatically log them in)
// For simplicity, we just confirm registration here. User needs to login separately.
res.status(201).json({ message: 'Registrierung erfolgreich. Bitte einloggen.' });
} catch (error) {
console.error('Registration Error:', error);
res.status(500).json({ message: 'Serverfehler bei der Registrierung.' });
}
});
// POST /api/auth/login - User Login
router.post('/login', async (req, res) => {
const { username, password } = req.body;
if (!username || !password) {
return res.status(400).json({ message: 'Benutzername und Passwort sind erforderlich.' });
}
try {
// Find user by username
const result = await db.query('SELECT * FROM users WHERE username = $1', [username]);
const user = result.rows[0];
// Check if user exists and password is correct
if (!user || !(await bcrypt.compare(password, user.password_hash))) {
return res.status(401).json({ message: 'Ungültiger Benutzername oder Passwort.' }); // 401 Unauthorized
}
// User authenticated successfully, create JWT payload
const payload = {
id: user.id,
username: user.username
};
// Sign the JWT with a 24h expiration for testing purposes
const token = jwt.sign(payload, JWT_SECRET, { expiresIn: '24h' });
// Set JWT as an HTTP-Only cookie with correct settings
res.cookie('token', token, {
httpOnly: true,
secure: false, // Set to false for local development
maxAge: 24 * 60 * 60 * 1000, // 24 hours in milliseconds
sameSite: 'Lax'
});
console.log(`User logged in: ${user.username}`);
// Send success response
res.status(200).json({ message: 'Login erfolgreich.', username: user.username });
} catch (error) {
console.error('Login Error:', error);
res.status(500).json({ message: 'Serverfehler beim Login.' });
}
});
// POST /api/auth/logout - User Logout
router.post('/logout', (req, res) => {
// Clear the authentication cookie
res.clearCookie('token', {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'Lax'
});
console.log('User logged out');
res.status(200).json({ message: 'Logout erfolgreich.' });
});
// --- NEUE Route ---
// GET /api/auth/status - Check login status without causing redirect/error
router.get('/status', (req, res) => {
const token = req.cookies.token;
if (!token) {
// No token cookie found
return res.json({ loggedIn: false });
}
// Verify the existing token
jwt.verify(token, JWT_SECRET, (err, user) => {
if (err) {
// Token is invalid (e.g., expired, tampered)
console.log('Status check: Invalid token found, clearing cookie.');
res.clearCookie('token'); // Clear the invalid cookie
return res.json({ loggedIn: false });
}
// Token is valid
// Send back loggedIn status and username
return res.json({ loggedIn: true, username: user.username });
});
});
module.exports = router;