← 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 })
}
}