Secure Login Code PHP

25 views 145 lines Secure Login
PHP secure login code
PHP • 145 lines
<?php

session_start();

require_once "db.php";

/*
|--------------------------------------------------------------------------
| Generate CSRF Token
|--------------------------------------------------------------------------
*/
if (!isset($_SESSION['csrf_token'])) {

    $_SESSION['csrf_token'] = bin2hex(
        random_bytes(32)
    );
}

/*
|--------------------------------------------------------------------------
| Login Processing
|--------------------------------------------------------------------------
*/
$error = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {

    /*
    |--------------------------------------------------------------------------
    | Verify CSRF
    |--------------------------------------------------------------------------
    */
    if (
        !isset($_POST['csrf_token']) ||
        !hash_equals(
            $_SESSION['csrf_token'],
            $_POST['csrf_token']
        )
    ) {
        die("Invalid Request");
    }

    $username = trim($_POST['username'] ?? '');
    $password = $_POST['password'] ?? '';

    if (
        empty($username) ||
        empty($password)
    ) {
        $error = "All fields are required";
    } else {

        $stmt = $pdo->prepare(
            "SELECT id, username, password
             FROM users
             WHERE username = ?
             LIMIT 1"
        );

        $stmt->execute([$username]);

        $user = $stmt->fetch(PDO::FETCH_ASSOC);

        if (
            $user &&
            password_verify(
                $password,
                $user['password']
            )
        ) {

            /*
            |--------------------------------------------------------------------------
            | Session Fixation Protection
            |--------------------------------------------------------------------------
            */
            session_regenerate_id(true);

            $_SESSION['user_id'] = $user['id'];
            $_SESSION['username'] = $user['username'];

            header("Location: dashboard.php");
            exit;

        } else {

            sleep(1); // Basic brute-force delay

            $error = "Invalid username or password";
        }
    }
}
?>

<!DOCTYPE html>
<html>
<head>
    <title>Secure Login</title>
</head>
<body>

<h2>Login</h2>

<?php if($error): ?>
<p style="color:red;">
    <?= htmlspecialchars($error) ?>
</p>
<?php endif; ?>

<form method="post">

    <input
        type="hidden"
        name="csrf_token"
        value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>"
    >

    <label>Username</label>
    <br>
    <input
        type="text"
        name="username"
        required
    >

    <br><br>

    <label>Password</label>
    <br>
    <input
        type="password"
        name="password"
        required
    >

    <br><br>

    <button type="submit">
        Login
    </button>

</form>

</body>
</html>
Raw Code • 145 lines
<?php

session_start();

require_once "db.php";

/*
|--------------------------------------------------------------------------
| Generate CSRF Token
|--------------------------------------------------------------------------
*/
if (!isset($_SESSION['csrf_token'])) {

    $_SESSION['csrf_token'] = bin2hex(
        random_bytes(32)
    );
}

/*
|--------------------------------------------------------------------------
| Login Processing
|--------------------------------------------------------------------------
*/
$error = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {

    /*
    |--------------------------------------------------------------------------
    | Verify CSRF
    |--------------------------------------------------------------------------
    */
    if (
        !isset($_POST['csrf_token']) ||
        !hash_equals(
            $_SESSION['csrf_token'],
            $_POST['csrf_token']
        )
    ) {
        die("Invalid Request");
    }

    $username = trim($_POST['username'] ?? '');
    $password = $_POST['password'] ?? '';

    if (
        empty($username) ||
        empty($password)
    ) {
        $error = "All fields are required";
    } else {

        $stmt = $pdo->prepare(
            "SELECT id, username, password
             FROM users
             WHERE username = ?
             LIMIT 1"
        );

        $stmt->execute([$username]);

        $user = $stmt->fetch(PDO::FETCH_ASSOC);

        if (
            $user &&
            password_verify(
                $password,
                $user['password']
            )
        ) {

            /*
            |--------------------------------------------------------------------------
            | Session Fixation Protection
            |--------------------------------------------------------------------------
            */
            session_regenerate_id(true);

            $_SESSION['user_id'] = $user['id'];
            $_SESSION['username'] = $user['username'];

            header("Location: dashboard.php");
            exit;

        } else {

            sleep(1); // Basic brute-force delay

            $error = "Invalid username or password";
        }
    }
}
?>

<!DOCTYPE html>
<html>
<head>
    <title>Secure Login</title>
</head>
<body>

<h2>Login</h2>

<?php if($error): ?>
<p style="color:red;">
    <?= htmlspecialchars($error) ?>
</p>
<?php endif; ?>

<form method="post">

    <input
        type="hidden"
        name="csrf_token"
        value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>"
    >

    <label>Username</label>
    <br>
    <input
        type="text"
        name="username"
        required
    >

    <br><br>

    <label>Password</label>
    <br>
    <input
        type="password"
        name="password"
        required
    >

    <br><br>

    <button type="submit">
        Login
    </button>

</form>

</body>
</html>
Code copied to clipboard!