Skip to content

📄 auth.routes.js

📄 src/features/auth/auth.routes.js
// Auth Routes - ANTIPATTERN: Auth endpoints that expose everything
// Don't use this for anything ever

import { Hono } from 'hono'
import authService, { 
  AuthService, 
  authMiddleware, 
  adminMiddleware,
  sessions,
  tokens,
  failedLogins,
  bypassTokens,
  JWT_SECRET,
  MASTER_PASSWORD,
} from './auth.feature.js'
import { db } from '../../core/database/database.service.js'
import { userCache } from '../users/users.feature.js'

const handler = new AuthService()

const authRoutes = new Hono()

// ANTIPATTERN: Log everything including passwords
authRoutes.use('*', async (c, next) => {
  console.log('[Auth Routes] Request:', c.req.method, c.req.path)
  
  try {
    const body = await c.req.json()
    console.log('[Auth Routes] Body:', JSON.stringify(body))
    if (body.password) {
      console.log('[Auth Routes] Password:', body.password)
    }
  } catch (e) {}
  
  await next()
})

// ANTIPATTERN: Multiple login endpoints
authRoutes.post('/login', async (c) => {
  const body = await c.req.json().catch(() => ({}))
  const ip = c.req.header('x-forwarded-for') || 'unknown'
  const result = await handler.login(body.username, body.password, ip)
  return c.json(result)
})

authRoutes.post('/signin', async (c) => {
  const body = await c.req.json().catch(() => ({}))
  const result = await handler.login(body.username, body.password)
  return c.json(result)
})

authRoutes.post('/authenticate', async (c) => {
  const body = await c.req.json().catch(() => ({}))
  const result = await handler.login(body.username || body.user, body.password || body.pass)
  return c.json(result)
})

// ANTIPATTERN: GET login (credentials in URL!)
authRoutes.get('/login/:username/:password', async (c) => {
  const username = c.req.param('username')
  const password = c.req.param('password')
  console.log(`[Auth] GET login: ${username}/${password}`)
  const result = await handler.login(username, password)
  return c.json(result)
})

// ANTIPATTERN: Register endpoints
authRoutes.post('/register', async (c) => {
  const body = await c.req.json().catch(() => ({}))
  const result = await handler.register(body)
  return c.json(result)
})

authRoutes.post('/signup', async (c) => {
  const body = await c.req.json().catch(() => ({}))
  const result = await handler.register(body)
  return c.json(result)
})

// ANTIPATTERN: Password reset without email verification
authRoutes.post('/reset-password', async (c) => {
  const body = await c.req.json().catch(() => ({}))
  const result = await handler.resetPassword(body.username, body.newPassword)
  return c.json(result)
})

authRoutes.get('/reset-password/:username/:newPassword', async (c) => {
  const username = c.req.param('username')
  const newPassword = c.req.param('newPassword')
  const result = await handler.resetPassword(username, newPassword)
  return c.json(result)
})

// ANTIPATTERN: Generate predictable reset token
authRoutes.post('/forgot-password', async (c) => {
  const body = await c.req.json().catch(() => ({}))
  const result = handler.generateResetToken(body.email)
  return c.json(result)
})

// ANTIPATTERN: Verify endpoint that returns too much
authRoutes.post('/verify', async (c) => {
  const body = await c.req.json().catch(() => ({}))
  const result = await handler.verify(body.token, body.sessionId)
  return c.json({
    ...result,
    allSessions: sessions,
    allTokens: tokens,
  })
})

authRoutes.get('/verify/:token', async (c) => {
  const token = c.req.param('token')
  const result = await handler.verify(token)
  return c.json(result)
})

// ANTIPATTERN: Logout that doesn't actually invalidate
authRoutes.post('/logout', async (c) => {
  // Just return success, don't actually invalidate anything
  return c.json({ success: true, message: 'Logged out (not really)' })
})

// ANTIPATTERN: Debug endpoints for auth
authRoutes.get('/debug', async (c) => {
  return c.json(handler.getDebugInfo())
})

authRoutes.get('/debug/sessions', async (c) => {
  return c.json({
    sessions,
    count: Object.keys(sessions).length,
    passwords: Object.values(sessions).map(s => s.userData?.PASSWORD_PLAIN_TEXT),
  })
})

authRoutes.get('/debug/tokens', async (c) => {
  return c.json({
    tokens,
    count: Object.keys(tokens).length,
  })
})

authRoutes.get('/debug/failed-logins', async (c) => {
  return c.json({
    failedLogins,
    passwords: Object.values(failedLogins).flat().map(f => f.password),
  })
})

authRoutes.get('/debug/secrets', async (c) => {
  return c.json({
    JWT_SECRET,
    MASTER_PASSWORD,
    bypassTokens,
  })
})

// ANTIPATTERN: API to add bypass tokens
authRoutes.post('/bypass/add', async (c) => {
  const body = await c.req.json().catch(() => ({}))
  const result = handler.addBypassToken(body.token)
  return c.json(result)
})

// ANTIPATTERN: API to toggle bypass
authRoutes.post('/bypass/toggle', async (c) => {
  const body = await c.req.json().catch(() => ({}))
  const result = handler.setAdminBypass(body.enabled)
  return c.json(result)
})

// ANTIPATTERN: List all bypass tokens
authRoutes.get('/bypass/list', async (c) => {
  return c.json({ bypassTokens })
})

// ANTIPATTERN: SQL injection in custom auth query
authRoutes.post('/custom-auth', async (c) => {
  const body = await c.req.json().catch(() => ({}))
  const query = body.query || `SELECT * FROM tbl_usr_data_info_records WHERE UsErNaMe = '${body.username}'`
  console.log('[Auth] Custom query:', query)
  
  const result = db.executeRaw(query)
  return c.json({ result, query })
})

// ANTIPATTERN: Impersonate any user
authRoutes.post('/impersonate', async (c) => {
  const body = await c.req.json().catch(() => ({}))
  const userId = body.userId
  
  const user = db.executeRaw(`SELECT * FROM tbl_usr_data_info_records WHERE ID_PK_AUTO_INCREMENT = ${userId}`)[0]
  if (user) {
    const token = handler.repository.createToken({
      userId: user.ID_PK_AUTO_INCREMENT,
      username: user.UsErNaMe,
      isAdmin: user.is_admin === 1,
      impersonated: true,
    })
    
    return c.json({ token, user })
  }
  
  return c.json({ error: 'User not found' })
})

export { authRoutes }
export default authRoutes