← back to Letsbegin

app/api/auth/login/route.ts

76 lines

import { NextRequest, NextResponse } from 'next/server'
import { validateCredentials, AUTH_CONFIG } from '@/lib/auth'
import { cookies } from 'next/headers'

export async function POST(request: NextRequest) {
  try {
    // Read raw body and parse manually for debugging
    let rawBody = await request.text()

    // Fix bash shell escaping issues (e.g., \! becomes !)
    // JSON only allows these escape sequences: \" \\ \/ \b \f \n \r \t \uXXXX
    // Remove backslashes before characters that aren't valid JSON escapes
    // Handle both single backslash and double-escaped backslashes
    rawBody = rawBody
      .replace(/\\!/g, '!')  // Specifically handle \! -> !
      .replace(/\\([^"\\/bfnrtu])/g, '$1')  // Handle other invalid escapes

    let username: string, password: string
    try {
      const body = JSON.parse(rawBody)
      username = body.username
      password = body.password
    } catch (parseErr) {
      // If still failing, try alternative parsing approaches
      console.error('JSON parse error:', parseErr, 'Raw body:', rawBody)

      // Try extracting credentials with regex as fallback
      const usernameMatch = rawBody.match(/"username"\s*:\s*"([^"]+)"/)
      const passwordMatch = rawBody.match(/"password"\s*:\s*"([^"\\]*(?:\\.[^"\\]*)*)"/)

      if (usernameMatch && passwordMatch) {
        username = usernameMatch[1]
        // Unescape the password manually
        password = passwordMatch[1].replace(/\\(.)/g, '$1')
      } else {
        return NextResponse.json({ error: 'Invalid JSON in request body' }, { status: 400 })
      }
    }

    if (!username || !password) {
      return NextResponse.json({ error: 'Username and password required' }, { status: 400 })
    }

    if (!validateCredentials(username, password)) {
      return NextResponse.json({ error: 'Invalid credentials' }, { status: 401 })
    }

    // Create session token
    const sessionData = {
      authenticated: true,
      username,
      loginTime: Date.now()
    }
    const sessionToken = Buffer.from(JSON.stringify(sessionData)).toString('base64')

    // Set cookie
    const cookieStore = await cookies()
    cookieStore.set(AUTH_CONFIG.sessionName, sessionToken, {
      httpOnly: true,
      secure: false, // Allow HTTP access for direct IP access
      sameSite: 'lax',
      maxAge: AUTH_CONFIG.cookieMaxAge / 1000, // Convert to seconds
      path: '/'
    })

    return NextResponse.json({
      success: true,
      message: 'Login successful',
      username
    })
  } catch (error) {
    console.error('Login error:', error)
    return NextResponse.json({ error: 'Login failed' }, { status: 500 })
  }
}