236 lines
5.6 KiB
JavaScript
236 lines
5.6 KiB
JavaScript
/**
|
|
* @openapi
|
|
* /api/v1/auth:
|
|
* post:
|
|
* summary: Admin login
|
|
* tags:
|
|
* - Authentication
|
|
* requestBody:
|
|
* required: true
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* required:
|
|
* - username
|
|
* - password
|
|
* properties:
|
|
* username:
|
|
* type: string
|
|
* password:
|
|
* type: string
|
|
* responses:
|
|
* 200:
|
|
* description: Login successful
|
|
* 401:
|
|
* description: Invalid credentials
|
|
* get:
|
|
* summary: Check session
|
|
* tags:
|
|
* - Authentication
|
|
* responses:
|
|
* 200:
|
|
* description: Session valid
|
|
* 401:
|
|
* description: Session invalid
|
|
*/
|
|
|
|
/*
|
|
* Authentication routes for the PoC application.
|
|
*
|
|
* Provides endpoints for:
|
|
* - POST /auth/admin/login - Admin login
|
|
* - POST /auth/user/login - User login
|
|
* - POST /auth/logout - Logout (both admin and user)
|
|
* - GET /auth/check - Check current session validity
|
|
*/
|
|
|
|
import { Router } from 'express';
|
|
import { asyncHandler } from '../utils/asyncHandler.js';
|
|
import {
|
|
verifyAdminCredentials,
|
|
verifyUserCredentials,
|
|
generateSessionToken,
|
|
createSession,
|
|
removeSession,
|
|
validateSession
|
|
} from '../services/authService.js';
|
|
|
|
const router = Router();
|
|
|
|
/**
|
|
* @openapi
|
|
* /api/v1/auth/admin/login:
|
|
* post:
|
|
* summary: Admin login
|
|
* tags:
|
|
* - Authentication
|
|
* requestBody:
|
|
* required: true
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* required:
|
|
* - username
|
|
* - password
|
|
* properties:
|
|
* username:
|
|
* type: string
|
|
* password:
|
|
* type: string
|
|
* responses:
|
|
* 200:
|
|
* description: Login successful
|
|
* 401:
|
|
* description: Invalid credentials
|
|
*/
|
|
router.post(
|
|
'/admin/login',
|
|
asyncHandler(async (req, res) => {
|
|
const { username, password } = req.body;
|
|
|
|
console.log(`PUBLIC: POST /api/v1/auth/admin/login - user: ${username}`);
|
|
|
|
if (!username || !password) {
|
|
return res.status(400).json({ success: false, message: 'Username and password required.' });
|
|
}
|
|
|
|
const result = await verifyAdminCredentials(username, password);
|
|
|
|
if (!result.valid) {
|
|
return res.status(401).json({ success: false, message: 'Invalid credentials.' });
|
|
}
|
|
|
|
const token = generateSessionToken();
|
|
createSession(token, { type: 'admin', ...result.admin });
|
|
|
|
/* Set cookie for browser-based auth */
|
|
res.cookie('auth_token', token, {
|
|
httpOnly: true,
|
|
maxAge: 24 * 60 * 60 * 1000, // 24 hours
|
|
sameSite: 'lax'
|
|
});
|
|
|
|
return res.json({ success: true, token, admin: result.admin });
|
|
})
|
|
);
|
|
|
|
/**
|
|
* @openapi
|
|
* /api/v1/auth/user/login:
|
|
* post:
|
|
* summary: User login
|
|
* tags:
|
|
* - Authentication
|
|
* requestBody:
|
|
* required: true
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* required:
|
|
* - email
|
|
* - password
|
|
* properties:
|
|
* email:
|
|
* type: string
|
|
* password:
|
|
* type: string
|
|
* responses:
|
|
* 200:
|
|
* description: Login successful
|
|
* 401:
|
|
* description: Invalid credentials
|
|
*/
|
|
router.post(
|
|
'/user/login',
|
|
asyncHandler(async (req, res) => {
|
|
const { email, password } = req.body;
|
|
|
|
console.log(`PUBLIC: POST /api/v1/auth/user/login - email: ${email}`);
|
|
|
|
if (!email || !password) {
|
|
return res.status(400).json({ success: false, message: 'Email and password required.' });
|
|
}
|
|
|
|
const result = await verifyUserCredentials(email, password);
|
|
|
|
if (!result.valid) {
|
|
return res.status(401).json({ success: false, message: 'Invalid credentials.' });
|
|
}
|
|
|
|
const token = generateSessionToken();
|
|
createSession(token, { type: 'user', ...result.user });
|
|
|
|
/* Set cookie for browser-based auth */
|
|
res.cookie('auth_token', token, {
|
|
httpOnly: true,
|
|
maxAge: 24 * 60 * 60 * 1000, // 24 hours
|
|
sameSite: 'lax'
|
|
});
|
|
|
|
return res.json({ success: true, token, user: result.user });
|
|
})
|
|
);
|
|
|
|
/**
|
|
* @openapi
|
|
* /api/v1/auth/logout:
|
|
* post:
|
|
* summary: Logout
|
|
* tags:
|
|
* - Authentication
|
|
* responses:
|
|
* 200:
|
|
* description: Logged out
|
|
*/
|
|
router.post('/logout', (req, res) => {
|
|
const token = req.cookies?.auth_token || req.headers.authorization?.replace('Bearer ', '');
|
|
|
|
console.log(`PUBLIC: POST /api/v1/auth/logout`);
|
|
|
|
if (token) {
|
|
removeSession(token);
|
|
}
|
|
|
|
res.clearCookie('auth_token');
|
|
return res.json({ success: true, message: 'Logged out.' });
|
|
});
|
|
|
|
/**
|
|
* @openapi
|
|
* /api/v1/auth/check:
|
|
* get:
|
|
* summary: Check session validity
|
|
* tags:
|
|
* - Authentication
|
|
* security:
|
|
* - cookieAuth: []
|
|
* responses:
|
|
* 200:
|
|
* description: Session valid
|
|
* 401:
|
|
* description: Session invalid
|
|
*/
|
|
router.get('/check', (req, res) => {
|
|
const token = req.cookies?.auth_token || req.headers.authorization?.replace('Bearer ', '');
|
|
|
|
console.log(`PUBLIC: GET /api/v1/auth/check`);
|
|
|
|
if (!token) {
|
|
return res.status(401).json({ authenticated: false, message: 'No session token.' });
|
|
}
|
|
|
|
const session = validateSession(token);
|
|
|
|
if (!session) {
|
|
res.clearCookie('auth_token');
|
|
return res.status(401).json({ authenticated: false, message: 'Session expired or invalid.' });
|
|
}
|
|
|
|
return res.json({ authenticated: true, session });
|
|
});
|
|
|
|
export default router;
|