I'm trying to do this basic api with jwt token based authentication tutorial. I've added all the code and I can add new users but cannot login. It always says 'Login failed. Email or password is incorrect.'. Could you please help me fix this? Thank you very much
You can view the whole project from here
user.php
<?php
// 'user' object
class User{
// database connection and table name
private $conn;
private $table_name = "users";
// object properties
public $id;
public $firstname;
public $lastname;
public $email;
public $password;
// constructor
public function __construct($db){
$this->conn = $db;
}
// create new user record
function create(){
// insert query
$query = "INSERT INTO " . $this->table_name . "
SET
firstname = :firstname,
lastname = :lastname,
email = :email,
password = :password";
// prepare the query
$stmt = $this->conn->prepare($query);
// sanitize
$this->firstname=htmlspecialchars(strip_tags($this->firstname));
$this->lastname=htmlspecialchars(strip_tags($this->lastname));
$this->email=htmlspecialchars(strip_tags($this->email));
//$this->password=htmlspecialchars(strip_tags($this->password));
// bind the values
$stmt->bindParam(':firstname', $this->firstname);
$stmt->bindParam(':lastname', $this->lastname);
$stmt->bindParam(':email', $this->email);
// hash the password before saving to database
$password_hash = password_hash($this->password, PASSWORD_BCRYPT);
$stmt->bindParam(':password', $password_hash);
// execute the query, also check if query was successful
if($stmt->execute()){
return true;
}
return false;
}
// check if given email exist in the database
function emailExists(){
// query to check if email exists
$query = "SELECT id, firstname, lastname, password
FROM " . $this->table_name . "
WHERE email = ?
LIMIT 0,1";
// prepare the query
$stmt = $this->conn->prepare( $query );
// sanitize
$this->email=htmlspecialchars(strip_tags($this->email));
// bind given email value
$stmt->bindParam(1, $this->email);
// execute the query
$stmt->execute();
// get number of rows
$num = $stmt->rowCount();
// if email exists, assign values to object properties for easy access and use for php sessions
if($num>0){
// get record details / values
$row = $stmt->fetch(PDO::FETCH_ASSOC);
// assign values to object properties
$this->id = $row['id'];
$this->firstname = $row['firstname'];
$this->lastname = $row['lastname'];
$this->password = $row['password'];
// return true because email exists in the database
return true;
}
// return false if email does not exist in the database
return false;
}
// update a user record
public function update(){
// if password needs to be updated
$password_set=!empty($this->password) ? ", password = :password" : "";
// if no posted password, do not update the password
$query = "UPDATE " . $this->table_name . "
SET
firstname = :firstname,
lastname = :lastname,
email = :email
{$password_set}
WHERE id = :id";
// prepare the query
$stmt = $this->conn->prepare($query);
// sanitize
$this->firstname=htmlspecialchars(strip_tags($this->firstname));
$this->lastname=htmlspecialchars(strip_tags($this->lastname));
$this->email=htmlspecialchars(strip_tags($this->email));
// bind the values from the form
$stmt->bindParam(':firstname', $this->firstname);
$stmt->bindParam(':lastname', $this->lastname);
$stmt->bindParam(':email', $this->email);
// hash the password before saving to database
if(!empty($this->password)){
$this->password=htmlspecialchars(strip_tags($this->password));
$password_hash = password_hash($this->password, PASSWORD_BCRYPT);
$stmt->bindParam(':password', $password_hash);
}
// unique ID of record to be edited
$stmt->bindParam(':id', $this->id);
// execute the query
if($stmt->execute()){
return true;
}
return false;
}
}
create_user.php
<?php
// required headers
header("Access-Control-Allow-Origin: http://localhost/rest-api-authentication-example/");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
// files needed to connect to database
include_once 'config/database.php';
include_once 'objects/user.php';
// get database connection
$database = new Database();
$db = $database->getConnection();
// instantiate product object
$user = new User($db);
// get posted data
$data = json_decode(file_get_contents("php://input"));
// set product property values
$user->firstname = $data->firstname;
$user->lastname = $data->lastname;
$user->email = $data->email;
$user->password = $data->password;
// create the user
if($user->create()){
// set response code
http_response_code(200);
// display message: user was created
echo json_encode(array("message" => "User was created."));
}
// message if unable to create user
else{
// set response code
http_response_code(400);
// display message: unable to create user
echo json_encode(array("message" => "Unable to create user."));
}
?>
login.php
<?php
// required headers
header("Access-Control-Allow-Origin: http://localhost/rest-api-authentication-example/");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
// files needed to connect to database
include_once 'config/database.php';
include_once 'objects/user.php';
// get database connection
$database = new Database();
$db = $database->getConnection();
// instantiate user object
$user = new User($db);
// get posted data
$data = json_decode(file_get_contents("php://input"));
// set product property values
$user->email = $data->email;
$email_exists = $user->emailExists();
// generate json web token
include_once 'config/core.php';
include_once 'libs/php-jwt-master/src/BeforeValidException.php';
include_once 'libs/php-jwt-master/src/ExpiredException.php';
include_once 'libs/php-jwt-master/src/SignatureInvalidException.php';
include_once 'libs/php-jwt-master/src/JWT.php';
use \Firebase\JWT\JWT;
// check if email exists and if password is correct
if($email_exists && password_verify($data->password, $user->password)){
$token = array(
"iss" => $iss,
"aud" => $aud,
"iat" => $iat,
"nbf" => $nbf,
"data" => array(
"id" => $user->id,
"firstname" => $user->firstname,
"lastname" => $user->lastname,
"email" => $user->email
)
);
// set response code
http_response_code(200);
// generate jwt
$jwt = JWT::encode($token, $key);
echo json_encode(
array(
"message" => "Successful login.",
"jwt" => $jwt
)
);
}
// login failed
else{
// set response code
http_response_code(401);
// tell the user login failed
echo json_encode(array("message" => "Login failed."));
}
?>
update_user.php
<?php
// required headers
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
// required to encode json web token
include_once 'config/core.php';
include_once 'libs/php-jwt-master/src/BeforeValidException.php';
include_once 'libs/php-jwt-master/src/ExpiredException.php';
include_once 'libs/php-jwt-master/src/SignatureInvalidException.php';
include_once 'libs/php-jwt-master/src/JWT.php';
use \Firebase\JWT\JWT;
// files needed to connect to database
include_once 'config/database.php';
include_once 'objects/user.php';
// get database connection
$database = new Database();
$db = $database->getConnection();
// instantiate user object
$user = new User($db);
// get posted data
$data = json_decode(file_get_contents("php://input"));
// get jwt
$jwt=isset($data->jwt) ? $data->jwt : "";
// if jwt is not empty
if($jwt){
// if decode succeed, show user details
try {
// decode jwt
$decoded = JWT::decode($jwt, $key, array('HS256'));
// set user property values
$user->firstname = $data->firstname;
$user->lastname = $data->lastname;
$user->email = $data->email;
$user->password = $data->password;
$user->id = $decoded->data->id;
// create the product
if($user->update()){
// we need to re-generate jwt because user details might be different
$token = array(
"iss" => $iss,
"aud" => $aud,
"iat" => $iat,
"nbf" => $nbf,
"data" => array(
"id" => $user->id,
"firstname" => $user->firstname,
"lastname" => $user->lastname,
"email" => $user->email
)
);
$jwt = JWT::encode($token, $key);
// set response code
http_response_code(200);
// response in json format
echo json_encode(
array(
"message" => "User was updated.",
"jwt" => $jwt
)
);
}
// message if unable to update user
else{
// set response code
http_response_code(401);
// show error message
echo json_encode(array("message" => "Unable to update user."));
}
}
// if decode fails, it means jwt is invalid
catch (Exception $e){
// set response code
http_response_code(401);
// show error message
echo json_encode(array(
"message" => "Access denied.",
"error" => $e->getMessage()
));
}
}
// show error message if jwt is empty
else{
// set response code
http_response_code(401);
// tell the user access denied
echo json_encode(array("message" => "Access denied."));
}
?>
validate_token.php
<?php
// required headers
header("Access-Control-Allow-Origin: http://localhost/rest-api-authentication-example/");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
// required to decode jwt
include_once 'config/core.php';
include_once 'libs/php-jwt-master/src/BeforeValidException.php';
include_once 'libs/php-jwt-master/src/ExpiredException.php';
include_once 'libs/php-jwt-master/src/SignatureInvalidException.php';
include_once 'libs/php-jwt-master/src/JWT.php';
use \Firebase\JWT\JWT;
// get posted data
$data = json_decode(file_get_contents("php://input"));
// get jwt
$jwt=isset($data->jwt) ? $data->jwt : "";
// if jwt is not empty
if($jwt){
// if decode succeed, show user details
try {
// decode jwt
$decoded = JWT::decode($jwt, $key, array('HS256'));
// set response code
http_response_code(200);
// show user details
echo json_encode(array(
"message" => "Access granted.",
"data" => $decoded->data
));
}
// if decode fails, it means jwt is invalid
catch (Exception $e){
// set response code
http_response_code(401);
// tell the user access denied & show error message
echo json_encode(array(
"message" => "Access denied.",
"error" => $e->getMessage()
));
}
}
// show error message if jwt is empty
else{
// set response code
http_response_code(401);
// tell the user access denied
echo json_encode(array("message" => "Access denied."));
}
?>