Sunday, October 11, 2020

PHP JWT & REST API Authentication Tutorial: Login and Signup

 In this tutorial, we'll learn how to add JWT authentication to our REST API PHP application.

We'll see what JWT is and how it works. We'll also see how to get the authorization header in PHP.

We'll create REST API endpoints for allowing users to login and signup to access protected resources.

What is JWT

JWT stands for JSON Web Token and comprised of user encrypted information that can be used to authenticate users and exchange information between clients and servers.

When building REST API, instead of server sessions commonly used in PHP apps we tokens which are sent with HTTP headers from the server to clients where they are persisted (usually using local storage) then attached to every outgoing request originating from the client to the server. The server checks the token and allow or deny access to the request resource.

RESTful APIs are stateless. This means that requests from clients should contain all the necessary information required to process the request.

If you are building a REST API application using PHP, you are not going to use the $_SESSION variable to save data about the client's session.

This means, we can not access the state of a client (such as login state). In order to solve the issue, the client is responsible for perisiting the state locally and send it to the sever with each request.

Since these important information are now persisted in the client local storage we need to protect it from eyes dropping.

Enter JWTs. A JWT token is simply a JSON object that has information about the user. For example:

{
    "user": "bob",
    "email": "bob@email.com",
    "access_token": "at145451sd451sd4e5r4",
    "expire_at"; "11245454"
}

Since thos token can be tampered with to get access to protected resources. For example, a malicious user can change the previous token as follows to access admin only resources on the server:

{
    "user": "administrator",
    "email": "admin@email.com"
}

To prevent this situation, we JWTs need to be signed by the server. If the token is changed on the client side, the token's signature will no longer be valid and the server will deny access to the requested resource.

How JWT Works

JWT tokens are simply encrypted user's information like identifier, username, email and password.

When users are successfully logged in the server, the latter will produce and send a JWT token back to the client.

This JWT token will be persisted by the client using the browser's local storage or cookies and attached with every outgoing request so if the user requests access to certain protected resources, the token needs to be checked first by the server to allow or deny access.

What is PHP-JWT

php-jwt is a PHP library that allows you to encode and decode JSON Web Tokens (JWT) in PHP, conforming to RFC 7519.

Prerequisites

You must have the following prerequsites to be able to follow this tutorial from scratch:

  • You need PHP 7, Composer and MySQL database system installed on your development environment,
  • You need to have basic knowledge of PHP and SQL.

Creating the MySQL Database and Table(s)

If you have the prerequisites, let's get started by creating the MySQL database. We'll be using the MySQL client installed with the server. Open a terminal and run the following command to invoke the client:

$ mysql -u root -p

You need to enter your MySQL password when prompted.

Next, let's create a database using the following SQL instruction:

mysql> create database db;

Note: Here we assume you have a MySQL user called root. You need to change that to the name of an existing MySQL user.

You can also use phpMyAdmin or any MySQL client you are comfortable with to create the database and SQL tables.

Let's now select the db database and create a users table that will hold the users of our application:

mysql> use db;
mysql> CREATE  TABLE IF NOT EXISTS `Users` (
  `id` INT  AUTO_INCREMENT ,
  `first_name` VARCHAR(150) NOT NULL ,
  `last_name` VARCHAR(150) NOT NULL ,
  `email` VARCHAR(255),
  `password` VARCHAR(255),
  PRIMARY KEY (`id`) );

Creating the Project Directory Structure

Let's create a simple directory strucutre for our project. In your terminal, navigate to your working directory and create a folder for our project:

$ mkdir php-jwt-example
$ cd php-jwt-example
$ mkdir api && cd api
$ mkdir config

We first created the project's directory.

Next, we created an api folder. Inside it, we created a config folder.

Connecting to your MySQL Database in PHP

Navigate to the config folder and create a database.php file with the following code:

<?php
// used to get mysql database connection
class DatabaseService{

    private $db_host = "localhost";
    private $db_name = "mydb";
    private $db_user = "root";
    private $db_password = "";
    private $connection;

    public function getConnection(){

        $this->connection = null;

        try{
            $this->connection = new PDO("mysql:host=" . $this->db_host . ";dbname=" . $this->db_name, $this->db_user, $this->db_password);
        }catch(PDOException $exception){
            echo "Connection failed: " . $exception->getMessage();
        }

        return $this->connection;
    }
}
?>

Installing php-jwt

Let's now proceed to install the php-jwt library using Composer. In your terminal, run the following command from the root of your project's directory:

$ composer require firebase/php-jwt

This will donwload the php-jwt library into a vendor folder.

You can require the php-jwt library to encode and decode JWT tokens using the following code:

<?php 
require "vendor/autoload.php";
use \Firebase\JWT\JWT;

Adding the User Registration API Endpoint

Inside the api folder, create a register.php file and add the following code to create a new user in the MySQL database:

<?php
include_once './config/database.php';

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");

$firstName = '';
$lastName = '';
$email = '';
$password = '';
$conn = null;

$databaseService = new DatabaseService();
$conn = $databaseService->getConnection();

$data = json_decode(file_get_contents("php://input"));

$firstName = $data->first_name;
$lastName = $data->last_name;
$email = $data->email;
$password = $data->password;

$table_name = 'Users';

$query = "INSERT INTO " . $table_name . "
                SET first_name = :firstname,
                    last_name = :lastname,
                    email = :email,
                    password = :password";

$stmt = $conn->prepare($query);

$stmt->bindParam(':firstname', $firstName);
$stmt->bindParam(':lastname', $lastName);
$stmt->bindParam(':email', $email);

$password_hash = password_hash($password, PASSWORD_BCRYPT);

$stmt->bindParam(':password', $password_hash);


if($stmt->execute()){

    http_response_code(200);
    echo json_encode(array("message" => "User was successfully registered."));
}
else{
    http_response_code(400);

    echo json_encode(array("message" => "Unable to register the user."));
}
?>

Adding the User Login API Endpoint

Inside the api folder, create a login.php file and add the following code to check the user credentials and return a JWT token to the client:

<?php
include_once './config/database.php';
require "../vendor/autoload.php";
use \Firebase\JWT\JWT;

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");


$email = '';
$password = '';

$databaseService = new DatabaseService();
$conn = $databaseService->getConnection();



$data = json_decode(file_get_contents("php://input"));

$email = $data->email;
$password = $data->password;

$table_name = 'Users';

$query = "SELECT id, first_name, last_name, password FROM " . $table_name . " WHERE email = ? LIMIT 0,1";

$stmt = $conn->prepare( $query );
$stmt->bindParam(1, $email);
$stmt->execute();
$num = $stmt->rowCount();

if($num > 0){
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    $id = $row['id'];
    $firstname = $row['first_name'];
    $lastname = $row['last_name'];
    $password2 = $row['password'];

    if(password_verify($password, $password2))
    {
        $secret_key = "owt56789"; //add here your secret key
        $issuer_claim = "localhost"; // this can be the servername
        $audience_claim = "myusers"; //your audience
        $issuedat_claim = time(); // issued at
        $notbefore_claim = $issuedat_claim + 10; //not before in seconds
        $expire_claim = $issuedat_claim + 60; // expire time in seconds
        $token = array(
            "iss" => $issuer_claim,
            "aud" => $audience_claim,
            "iat" => $issuedat_claim,
            "nbf" => $notbefore_claim,
            "exp" => $expire_claim,
            "data" => array(
                "id" => $id,
                "firstname" => $firstname,
                "lastname" => $lastname,
                "email" => $email
        ));

        http_response_code(200);

        $jwt = JWT::encode($token, $secret_key);
        echo json_encode(
            array(
                "message" => "Successful login.",
                "jwt" => $jwt,
                "email" => $email,
                "expireAt" => $expire_claim
            ));
    }
    else{

        http_response_code(401);
        echo json_encode(array("message" => "Login failed.", "password" => $password));
    }
}
?>

You can define the data structure of the token as you want i.e (You can add only the user's email or ID or both with any extra information like the user's name) but there are some reserved JWT claims that should be defined properly because they affect the validity of the JWT token, such as:

  • iat – timestamp of token issuing.

  • iss – A string containing the name or identifier of the issuer application. Can be a domain name and can be used to discard tokens from other applications.

  • nbf – Timestamp of when the token should start being considered valid. Should be equal to or greater than iat. In this case, the token will begin to be valid after 10 seconds after being issued

  • exp – Timestamp of when the token should stop to be valid. Needs to be greater than iat and nbf. In our example, the token will expire after 60 seconds of being issued.

These claims are not required, but are useful for determining the validity of a token.

Our JWT payload is inside the data claim, we added the first name, last name, email and user ID from the database. You shouldn't add any sensitive information in the JWT payload.

The JWT::encode() method will transform the PHP array into JSON format and sign the payload then encode the final JWT token that will be sent to the client. In our example, we simply hradcoded the secret key that will be used for signing the JWT payload but in production, you need to make sure you use a secret key with a long, binary string, store it in a configuration file.

We now have two RESTful endpoints for registering and log users in. At this point, you can use a REST client like Postman to intercat with the API.

First, start your PHP server using the following command:

$ php -S 127.0.0.1:8080

A development server will be running from the 127.0.0.1:8080 address.

Let's now, create a user in the database by sending a POST request to the api/register.php endpoint with a JSON body that contains the first_namelast_nameemail and password:

PHP JWT Authentication Example

You should get an 200 HTTP response with a User was successfully registered. message.

Next, you need to send a POST request to the /api/login.php endpoint with a JSON body that contains the email and password used for registering the user:

PHP JWT Authentication Example

You should get a Successful login message with a JWT token.

The JWT token needs to be persisted in your browser's local storage or cookies using JavaScript then attached to each send HTTP request to access a protected resource on your PHP server.

Protecting an API Endpoint Using JWT

Let's now see how we can protected our server endpoints using JWT tokens.

Before accessing an endpoint a JWT token is sent with every request from the client. The server needs to decode the JWT and check if it's valid before allowing access to the endpoint.

Inside the api folder, create a protected.php file and add the following code:

<?php
include_once './config/database.php';
require "../vendor/autoload.php";
use \Firebase\JWT\JWT;

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");


$secret_key = "YOUR_SECRET_KEY";
$jwt = null;
$databaseService = new DatabaseService();
$conn = $databaseService->getConnection();

$data = json_decode(file_get_contents("php://input"));


$authHeader = $_SERVER['HTTP_AUTHORIZATION'];

$arr = explode(" ", $authHeader);


/*echo json_encode(array(
    "message" => "sd" .$arr[1]
));*/

$jwt = $arr[1];

if($jwt){

    try {

        $decoded = JWT::decode($jwt, $secret_key, array('HS256'));

        // Access is granted. Add code of the operation here 

        echo json_encode(array(
            "message" => "Access granted:",
            "error" => $e->getMessage()
        ));

    }catch (Exception $e){

    http_response_code(401);

    echo json_encode(array(
        "message" => "Access denied.",
        "error" => $e->getMessage()
    ));
}

}
?>

Note: We assume that the client sends the JWT token inside an HTTP Authorization header in the JWT <token> or Bearer <token> formats. You can also choose to include the token as a parameter in the request URL or as part of data payload sent from the client if you don't want to deal with HTTP headers.

You can now send a POST request with an Authorization header in the following formats:

JWT <YOUR_JWT_TOKEN_HERE> 

Or also using the bearer format:

Bearer <YOUR_JWT_TOKEN_HERE>

PHP JWT

Conclusion

In this tutorial, we've seen how to implement REST API JWT authentication in PHP and MySQL.

Credit & Source: https://www.techiediaries.com/php-jwt-authentication-tutorial/?fbclid=IwAR27DtqFhlZxec5lJV4Y0WOwUlFdFU9pinfQ7LZ8PjotI6zSXgyGp1ZlWcs


Friday, October 2, 2020

How to forbidden Right Click, ctrl+c, ctrl+u, and F12 with javascript

 // To disable right click

document.addEventListener('contextmenu', event => event.preventDefault());

// To disable F12 options

document.onkeypress = function (event) {

event = (event || window.event);

if (event.keyCode == 123) {

return false;

}

}

document.onmousedown = function (event) {

event = (event || window.event);

if (event.keyCode == 123) {

return false;

}

}

document.onkeydown = function (event) {

event = (event || window.event);

if (event.keyCode == 123) {

return false;

}

}

// To To Disable ctrl+c, ctrl+u

jQuery(document).ready(function($){

$(document).keydown(function(event) {

var pressedKey = String.fromCharCode(event.keyCode).toLowerCase();

if (event.ctrlKey && (pressedKey == "c" || pressedKey == "u")) {

alert('Sorry, This Functionality Has Been Disabled!');

//disable key press porcessing

return false;

}

});

});

Thursday, July 2, 2020

Replacing Background Colors in Cells

It's fairly obvious that you can change the background colors of any cells manually, so there is no need to go into that option for making the changes. What you need to do is use a simple tool, such as the Find and Replace tool, to make the color changes. Follow these steps:
  1. Press Ctrl+H to display the Replace tab of the Find and Replace dialog box.
  2. Expand the dialog box by clicking the Options button. (See Figure 1.)
  3. Figure 1. The Replace tab of the Find and Replace dialog box.
  4. Click the Format button at the right side of the Find What box. Excel displays the Find Format dialog box.
  5. Make sure the Fill tab is selected. (See Figure 2.)
  6. Figure 2. The Fill tab of the Find Format dialog box.
  7. Use the controls in the dialog box to specify the background color you want to replace.
  8. Click OK.
  9. Click the Format button at the right side of the Replace With box. Excel displays the Replace Format dialog box.
  10. Make sure the Fill tab is selected.
  11. Use the controls in the dialog box to specify the background color you used when changing the cells.
  12. Click OK.
  13. Click Replace All.
If you find yourself needing to make the same color changes over and over (for instance, always changing from red to blue), then you may be interested in using a macro to do the changes. The following example could be assigned to a shortcut key or added to the Quick Access Toolbar so you can use it quickly:
Sub ChangeColor()
    Dim rCell As Range
    If Selection.Cells.Count = 1 Then
        MsgBox "Select the range to be processed."
        Exit Sub
    End If
    For Each rCell In Selection
        If rCell.Interior.Color = RGB(255, 0, 0) Then  'red
            rCell.Interior.Color = RGB(0, 0, 255)      'blue
        End If
    Next rCell
End Sub

Friday, April 3, 2020

Drawing rotated text on a HTML5 canvas

Posting this in an effort to help others with similar problems. I solved this issue with a five step approach -- save the context, translate the context, rotate the context, draw the text, then restore the context to its saved state.
I think of translations and transforms to the context as manipulating the coordinate grid overlaid on the canvas. By default the origin (0,0) starts in the upper left hand corner of the canvas. X increases from left to right, Y increases from top to bottom. If you make an "L" w/ your index finger and thumb on your left hand and hold it out in front of you with your thumb down, your thumb would point in the direction of increasing Y and your index finger would point in the direction of increasing X. I know it's elementary, but I find it helpful when thinking about translations and rotations. Here's why:
When you translate the context, you move the origin of the coordinate grid to a new location on the canvas. When you rotate the context, think of rotating the "L" you made with your left hand in a clockwise direction the amount indicated by the angle you specify in radians about the origin. When you strokeText or fillText, specify your coordinates in relation to the newly aligned axes. To orient your text so it's readable from bottom to top, you would translate to a position below where you want to start your labels, rotate by -90 degrees and fill or strokeText, offsetting each label along the rotated x axis. Something like this should work:
 context.save();
 context.translate(newx, newy);
 context.rotate(-Math.PI/2);
 context.textAlign = "center";
 context.fillText("Your Label Here", labelXposition, 0);
 context.restore();
.restore() resets the context back to the state it had when you called .save() -- handy for returning things back to "normal".

Tuesday, March 17, 2020

How to add rowspan in table column if values is the same using jQuery

By using jQUery

<table border=1 id="myTable">
        <tr>
            <td>A</td>
            <td>1</td>
        </tr>
        <tr>
            <td>A</td>
            <td>2</td>
        </tr>
        <tr>
            <td>b</td>
            <td>1</td>
        </tr>
        <tr>
            <td>c</td>
            <td>1</td>
        </tr>
        <tr>
            <td>c</td>
            <td>1</td>
        </tr>
    </table>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>

<script>
    $(document).ready(function() {
       var span = 1;
       var prevTD = "";
       var prevTDVal = "";
       $("#myTable tr td:first-child").each(function() { //for each first td in every tr
          var $this = $(this);
          if ($this.text() == prevTDVal) { // check value of previous td text
             span++;
             if (prevTD != "") {
                prevTD.attr("rowspan", span); // add attribute to previous td
                $this.remove(); // remove current td
             }
          } else {
             prevTD     = $this; // store current td 
             prevTDVal  = $this.text();
             span       = 1;
          }
       });
    });
</script>

How to change the PHP version for subfolders or subdomains

  How to change the PHP version for subfolders or subdomains Setting a specific PHP version for a specific websites, subfolders or subdomain...