📄 Source: login.php
<?php
require_once __DIR__ . '/../auth.php';
header('Content-Type: application/json');
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
if ($username === '' || $password === '') {
http_response_code(400);
echo json_encode(['ok' => false, 'error' => 'Missing username or password']);
exit;
}
$u = users_verify($username, $password);
if ($u === null) {
http_response_code(401);
echo json_encode(['ok' => false, 'error' => 'Invalid credentials']);
exit;
}
// If device-bound and no token yet, issue one now.
if (!empty($u['device_bound'])) {
if (empty($u['device_token'])) {
$token = bin2hex(random_bytes(32));
users_bind_device($u['username'], $token);
setcookie($CFG['session_name'] . '_dev', $token, [
'expires' => time() + $CFG['session_lifetime'],
'path' => '/',
'httponly' => true,
'samesite' => 'Lax',
]);
} else {
$cookieName = $CFG['session_name'] . '_dev';
$token = $_COOKIE[$cookieName] ?? '';
if (!$token || !hash_equals((string)$u['device_token'], (string)$token)) {
http_response_code(403);
echo json_encode(['ok' => false, 'error' => 'This account is bound to another device']);
exit;
}
}
}
$_SESSION['username'] = $u['username'];
echo json_encode(['ok' => true, 'username' => $u['username'], 'is_owner' => !empty($u['is_owner'])]);
← Back