diff --git a/backend/src/controllers/auth.controller.ts b/backend/src/controllers/auth.controller.ts index 81749d7..c361989 100644 --- a/backend/src/controllers/auth.controller.ts +++ b/backend/src/controllers/auth.controller.ts @@ -6,81 +6,56 @@ import { LoggerService } from '../services/logger.service.js'; import { ACCESS_TOKEN_COOKIE_NAME, MEET_ACCESS_TOKEN_EXPIRATION, - MEET_ADMIN_USER, MEET_API_BASE_PATH_V1, MEET_REFRESH_TOKEN_EXPIRATION, REFRESH_TOKEN_COOKIE_NAME } from '../environment.js'; import { ClaimGrants } from 'livekit-server-sdk'; import { getCookieOptions } from '../utils/cookie-utils.js'; +import { UserService } from '../services/user.service.js'; -export const login = (req: Request, res: Response) => { +export const login = async (req: Request, res: Response) => { const logger = container.get(LoggerService); logger.verbose('Login request received'); - const { username, password } = req.body; - - if (!username || !password) { - logger.warn('Missing username or password'); - return res.status(400).json({ message: 'Missing username or password' }); - } + const { username, password } = req.body as { username: string; password: string }; const authService = container.get(AuthService); - const authenticated = authService.authenticateUser(username, password); + const user = authService.authenticate(username, password); - if (!authenticated) { + if (!user) { logger.warn('Login failed'); - return res.status(401).json({ message: 'Login failed' }); - } - - return res.status(200).json({ message: 'Login succeeded' }); -}; - -export const logout = (req: Request, res: Response) => { - return res.status(200).json({ message: 'Logout successful' }); -}; - -export const adminLogin = async (req: Request, res: Response) => { - const logger = container.get(LoggerService); - logger.verbose('Admin login request received'); - const { username, password } = req.body; - - const authService = container.get(AuthService); - const authenticated = authService.authenticateAdmin(username, password); - - if (!authenticated) { - logger.warn(`Admin login failed for username: ${username}`); - return res.status(404).json({ message: 'Admin login failed. Invalid username or password' }); + return res.status(404).json({ message: 'Login failed. Invalid username or password' }); } try { const tokenService = container.get(TokenService); - const accessToken = await tokenService.generateAccessToken(username); - const refreshToken = await tokenService.generateRefreshToken(username); + const accessToken = await tokenService.generateAccessToken(user); + const refreshToken = await tokenService.generateRefreshToken(user); res.cookie(ACCESS_TOKEN_COOKIE_NAME, accessToken, getCookieOptions('/', MEET_ACCESS_TOKEN_EXPIRATION)); res.cookie( REFRESH_TOKEN_COOKIE_NAME, refreshToken, - getCookieOptions(`${MEET_API_BASE_PATH_V1}/auth/admin`, MEET_REFRESH_TOKEN_EXPIRATION) + getCookieOptions(`${MEET_API_BASE_PATH_V1}/auth`, MEET_REFRESH_TOKEN_EXPIRATION) ); - logger.info(`Admin login succeeded for username: ${username}`); - return res.status(200).json({ message: 'Admin login succeeded' }); + logger.info(`Login succeeded for user ${username}`); + return res.status(200).json({ message: 'Login succeeded' }); } catch (error) { - logger.error('Error generating admin token' + error); + logger.error('Error generating token' + error); return res.status(500).json({ message: 'Internal server error' }); } }; -export const adminLogout = (req: Request, res: Response) => { +export const logout = (_req: Request, res: Response) => { res.clearCookie(ACCESS_TOKEN_COOKIE_NAME); res.clearCookie(REFRESH_TOKEN_COOKIE_NAME, { - path: `${MEET_API_BASE_PATH_V1}/auth/admin` + path: `${MEET_API_BASE_PATH_V1}/auth` }); return res.status(200).json({ message: 'Logout successful' }); }; -export const adminRefresh = async (req: Request, res: Response) => { +export const refreshToken = async (req: Request, res: Response) => { const logger = container.get(LoggerService); - logger.verbose('Admin refresh request received'); + logger.verbose('Refresh token request received'); const refreshToken = req.cookies[REFRESH_TOKEN_COOKIE_NAME]; if (!refreshToken) { @@ -98,18 +73,32 @@ export const adminRefresh = async (req: Request, res: Response) => { return res.status(400).json({ message: 'Invalid refresh token' }); } - if (payload.sub !== MEET_ADMIN_USER) { + const username = payload.sub; + const userService = container.get(UserService); + const user = username ? userService.getUser(username) : null; + + if (!user) { logger.warn('Invalid refresh token subject'); return res.status(403).json({ message: 'Invalid refresh token subject' }); } try { - const accessToken = await tokenService.generateAccessToken(MEET_ADMIN_USER); + const accessToken = await tokenService.generateAccessToken(user); res.cookie(ACCESS_TOKEN_COOKIE_NAME, accessToken, getCookieOptions('/', MEET_ACCESS_TOKEN_EXPIRATION)); - logger.info(`Admin refresh succeeded for username: ${MEET_ADMIN_USER}`); - return res.status(200).json({ message: 'Admin refresh succeeded' }); + logger.info(`Token refreshed for user ${username}`); + return res.status(200).json({ message: 'Token refreshed' }); } catch (error) { - logger.error('Error refreshing admin token' + error); + logger.error('Error refreshing token' + error); return res.status(500).json({ message: 'Internal server error' }); } }; + +export const getProfile = (req: Request, res: Response) => { + const user = req.session?.user; + + if (!user) { + return res.status(401).json({ message: 'Unauthorized' }); + } + + return res.status(200).json(user); +}; diff --git a/backend/src/routes/auth.routes.ts b/backend/src/routes/auth.routes.ts index 110b276..1266ebb 100644 --- a/backend/src/routes/auth.routes.ts +++ b/backend/src/routes/auth.routes.ts @@ -1,27 +1,29 @@ -import { Router, Request, Response } from 'express'; +import { Router } from 'express'; import bodyParser from 'body-parser'; import * as authCtrl from '../controllers/auth.controller.js'; import rateLimit from 'express-rate-limit'; -import { withAdminValidToken } from '../middlewares/auth.middleware.js'; +import { tokenAndRoleValidator, withAuth } from '../middlewares/auth.middleware.js'; +import { Role } from '@typings-ce'; +import { validateLoginRequest } from '../middlewares/request-validators/auth-validator.middleware.js'; export const authRouter = Router(); // Limit login attempts for avoiding brute force attacks const loginLimiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 min - max: 5, - message: 'Too many login attempts, please try again later.' + limit: 5, + message: 'Too many login attempts, please try again later' }); authRouter.use(bodyParser.urlencoded({ extended: true })); authRouter.use(bodyParser.json()); // Auth Routes -authRouter.post('/login', authCtrl.login); +authRouter.post('/login', validateLoginRequest, loginLimiter, authCtrl.login); authRouter.post('/logout', authCtrl.logout); -authRouter.post('/admin/login', loginLimiter, authCtrl.adminLogin); -authRouter.post('/admin/logout', authCtrl.adminLogout); -authRouter.post('/admin/refresh', authCtrl.adminRefresh); -authRouter.get('/admin/verify', withAdminValidToken, (_req: Request, res: Response) => - res.status(200).json({ message: 'Valid token' }) +authRouter.post('/refresh', authCtrl.refreshToken); +authRouter.get( + '/profile', + withAuth(tokenAndRoleValidator(Role.ADMIN), tokenAndRoleValidator(Role.USER)), + authCtrl.getProfile );