PHP registration/login form I'm fairly new to MySQLi and PHP, but I've been working at it for a bit now, and reading up on how to make secure login forms, avoid SQL injection etc. I'm a mere amateur though.

I've created an index.html page (not including the code here, just a basic form though), a register.html page (not including the code here, again it's just a basic form), adduser.php (which gets its call from "action" on the registration form),login.php (obviously gets its "action" from the index.html login form), logout.php, and a restricted.php with a check if session is active.

Everything is working. I'm just looking for some expert eyes to take a gander at my code and let me know if I'm missing anything whether it be major or minor, any security flaws, etc. Currently I don't have any form validation as I'm thinking of doing it client side with jQuery.

adduser.php

&lt;?php

error_reporting(E_ALL);
session_start();
$mysqli = new mysqli ('localhost', '***', '***', 'test');

if($mysqli-&gt;connect_errno &gt; 0) {
    die('Unable to connect to database [' . $mysqli-&gt;connect_error . ']');
}


if(isset($_POST['submit'])) {

    $errors = array();
    $data = array();
    $fname = $_POST['fname'];
    $lname = $_POST['lname'];
    $username = $_POST['username'];
    $email = $_POST['email'];
    $password = $_POST['password'];
    $confpass = $_POST['confpass'];
    $password_hash = password_hash($password, PASSWORD_DEFAULT);    

    if(!($stmt = $mysqli-&gt;prepare("INSERT INTO users (fname, lname, username, email, password) 
        VALUES (?,?,?,?,?)"))){
        echo "Prepare failed: (" . $mysqli-&gt;errno . ")" . $mysqli-&gt;error;
    }

    if(!$stmt-&gt;bind_param('sssss', $fname, $lname, $username, $email, $password_hash)){
     echo "Binding paramaters failed:(" . $stmt-&gt;errno . ")" . $stmt-&gt;error;
    }

    if(!$stmt-&gt;execute()){
     echo "Execute failed: (" . $stmt-&gt;errno .")" . $stmt-&gt;error;
    }

    if($stmt) {
        header('Location: index.html#testform')

    }
    else{
        echo "Registration failed";
    }

}

$mysqli-&gt;close();


login.php

&lt;?php
error_reporting(E_ALL);

$mysqli = new mysqli ('localhost', '***', '***', 'test');

if($mysqli-&gt;connect_errno &gt; 0) {
    die('Unable to connect to database [' . $mysqli-&gt;connect_error . ']');
}
ob_start();
session_start();

    $username = $_POST['username'];
    $password = $_POST['password'];
if(isset($_POST['submit'])) {

    if(!($stmt = $mysqli-&gt;prepare("SELECT username, password FROM users WHERE username = ?"))){
            echo "Prepare failed: (" . $mysqli-&gt;errno . ")" . $mysqli-&gt;error;
    }




    if(!$stmt-&gt;bind_param('s', $username)){
        echo "Bind failed: (" . $stmt-&gt;errno . ")" . $stmt-&gt;error;
    }

    if(!$stmt-&gt;execute()){
     echo "Execute failed: (" . $stmt-&gt;errno .")" . $stmt-&gt;error;
    }

    $userdata = $stmt-&gt;get_result();
    $row = $userdata-&gt;fetch_array(MYSQLI_ASSOC);



    $stmt-&gt;bind_result($username, $password);
    $stmt-&gt;store_result();

             if(password_verify($password, $row['password'])){

            $_SESSION['user'] = $_POST['username'];
            header('Location: restricted.php');
            exit();
        }


    else{
        echo "Login Failed: (" . $stmt-&gt;errno .")" . $stmt-&gt;error;
    }
$stmt-&gt;close();

}

$mysqli-&gt;close();




restricted.php (just the top session code, the rest of the page is useless for the sake of this post)

&lt;?php
error_reporting(E_ALL);
ob_start();
session_start();
$db = new mysqli ('localhost', '***', '***', 'test');

if($db-&gt;connect_errno &gt; 0) {
    die('Unable to connect to database [' . $db-&gt;connect_error . ']');
}
if (!isset($_SESSION['user'])) {
    header('Location: index.html');
}


?&gt;




logout.php

&lt;?php
session_start();
if(session_destroy()) // Destroying All Sessions
{
header("Location: index.html"); // Redirecting To Home Page
}
?&gt;
Security

First of, your code looks pretty good, especially from a security point of view. You use prepared statements, and you use them correctly, and you use bcrypt instead of some weaker hashing algorithm such as md5 or sha.

There are a couple of things which might cause problems under certain conditions, and as defense in depth it might be a good idea to include them:


always die after a redirect, because the redirect does not necessarily stop execution of the PHP script (you can easily test this yourself: header('Location: index.html'); echo "secret"; using curl: curl localhost/redirect.php would give you secret, because curl doesn't follow redirects by default).
you have new mysqli ([credentials]) in at least two places. This is not only bad because duplication makes code harder to read and maintain, with credentials it is especially bad because it makes it harder to remember to hide them (when posting code somewhere else, submitting it in version control, etc). It also makes it harder to move those PHP files that do contain credentials outside the web root. Just put the database connection in one file (located outside the web root) and wrap it in a getConnection function (this also makes it possible to use the same database connection for all queries, which improves performance).
with current default PHP.ini settings, this is less important, but it is still always a good idea to regenerate the session id when the state of the session changes (eg when logging in) to prevent session fixation.
as @sjonniesjon said, don't echo actual error messages to the user. It can directly enable some attacks such SQL injections into some keywords (such as insert, update, order by, etc) which only display data in error messages, and it can help an attacker identify vulnerabilities.


Misc


your indentation is sometimes off, leading to harder to read code. Your brackets are also placed inconsistently.
you also have too many newlines in some places.