PHP API Authentication Using JWT
Hariket Sukeshkumar Sheth
SDE @ Societe Generale ? Samsung PRISM Developer ? Beta MLSA ?? ? MLH Fellow Summer'22 ? Ex. Intern at Linguee Global Solutions ? Full Stack Enthusiast
While developing an application, security has become a critical factor to consider. As users grow more conscious of security issues and hackers become well-known, you'll need to implement mechanisms to improve the data security of your app.
Using session storage to safeguard apps was formerly commonplace. Sessions have become inefficient in recent years, prompting a migration to API-based authentication. Although this was a fantastic and reliable method of securing online applications, it became outdated as hackers attempted to breach it.
WHAT IS JWT?
JSON Online Token (JWT) is a secure method of authenticating users in a web application. You may send encrypted data information between a client computer and a server using JWT.
Choosing between?JWT?and?Session?is more than simply a matter of preference. To decide which one to utilize in an application, you must consider many variables. Now let us compare both of them and understand their difference.
Server-Side Sessions
Assume you have a website that has a login form. Your browser sends a request to the server when you input your email ID and password. Your server compares the password hashes, and if they match, a session with a unique session ID is generated. The server then delivers a cookie with the session ID, which is HTTP-only. Hence cannot be read by any javascript other than yours. It's also protected so that the cookie is never sent via an insecure connection. Otherwise, someone, such as a man in the middle attack, might intercept the conversation.
Client-side Sessions Work with JWT
You verify whether the password hashes match instead of starting a session in your session storage. If they do match, all you have to do now is produce a JSON signature token. The token is signed with the secret. If someone tries to change the payload notification will be rolled out and, the signature validation will fail.
You may return a web signature token stored in a cookie, which is much more convenient. Because if you don't, a third-party javascript may be able to access it.
STATELESSNESS AND PROBLEMS WITH JWT
Consider the following scenario: a bank client's personal information is compromised, and the consumer phones the bank to request that the account be locked. Because JWT is stateless, there will be a problem if the bank utilizes it for authentication. Although adding a state may be used to get around this, it contradicts the purpose of having a JWT Token as it risks logging everyone out, including the customer. Because the client's status is saved, logging out that one customer won't be a problem.
ATTACKS IN JWT AND SESSION-BASED SYSTEMS
Because authentication tokens are delivered via the network, they are subject to attacks. Although such attacks are unlikely, it is critical to take security seriously and deploy necessary safeguards. The system's susceptibility is determined by the combined probability of all forms of attacks. You may mitigate the attack in a few ways:
PHP API SECURITY USING JWTs
Now that you know everything there is to know about JWT, let's use it to protect your PHP API. If you follow the code step by step, you'll end up with a tamper-proof PHP API.
This post provides a basic login page and uses JWT to authenticate it. This guide will assist you in getting started with JWT and PHP.
You'll need PHP and composer installed on your PC to follow along. If you haven't already done so, you may learn how to install composer on your computer here.
Run composer from your project folder after you've installed it. Firebase PHP-JWT, a third-party library for working with JWTs and Apache, will be installed with Composer's help.
<?php
declare(strict_types=1);
use Firebase\JWT\JWT;
require_once('../vendor/autoload.php');
After the form is submitted, you must cross-reference the data entered with a data source or database. Let's make a hasValidCredentials variable and set it to true for our purposes. When this variable is set to true, the data has been reviewed and is legitimate.
领英推荐
<?php
if ($hasValidCredentials) {
Any further coding will be included within this block. All functionality related to the creation and validation of the needed JWT is governed by the value of the hasValidCredentials variable. The JWT will be produced if its value is true; else, an error will be shown.
CREATING JWT
To help with this procedure, you'll need to create some extra variables first.
Client-side browsers may simply inspect and validate JWTs. As a result, it's best to store your secret key and other sensitive data in an environment file that the user can't access via client-side queries.
$secret_Key = 'ENTER_SECRET_KEY_HERE'
$date = new DateTimeImmutable();
$expire_at = $date->modify('+6 minutes')->getTimestamp();
$domainName = "your.domain.name";
$username = "username";
$request_data = [
'iat' => $date->getTimestamp(),
'iss' => $domainName,
'nbf' => $date->getTimestamp(),
'exp' => $expire_at,
'userName' => $username,
];
Now that you have all of the necessary information, you can easily build a JWT. The encode() function from the PHP-JWT library will be used here. This technique aids in the conversion of your data array to a JSON object.
The encode function creates JWT headers and signs the incoming payload with a cryptographic combination of all the information and the specified secret key after converting to a JSON object.
To use the encode() function successfully, you must provide it with three parameters. The payload information, which in this case is the data array, should be the first parameter. Second, you must pass the secret key as an input to the function, and third, you must specify the cryptographic technique that the function should use to sign the JWT.
<?php
// Encode the array to a JWT string.
echo JWT::encode(
$request_data,
$secret_Key,
'HS512'
);
}
After you've got the JWT token, you may use any web programming language to transmit it to the client-side and preserve it. Let's get started with a little JS example of the path ahead.
First, save the produced and received JWT in client-side memory after successful form submission. Remove the login form and replace it with a button that retrieves and shows the JWT's timestamp to the user when clicked.
const storeJWT = {}
const loginBtn = document.querySelector("#frmLogin")
const btnResource = document.querySelector("#btnGetResource")
const formData = document.forms[0]
storeJWT.setJWT = function (data) {
this.JWT = data
}
loginBtn.addEventListener("submit", async e => {
e.preventDefault()
const response = await fetch("/authenticate.php", {
method: "POST",
headers: {
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8",
},
body: JSON.stringify({
username: formData.inputEmail.value,
password: formData.inputPassword.value,
}),
})
if (response.status >= 200 && response.status <= 299) {
const jwt = await response.text()
storeJWT.setJWT(jwt)
frmLogin.style.display = "none"
btnResource.style.display = "block"
} else {
console.log(response.status, response.statusText)
}
})
JWT VALIDATION
Everything should be all right if you've followed up to this point. Let's get started verifying the JWT.
You've already used the composer's autoloader tool to assist you with this task. To extract the token from the Bearer header, use the preg match function. You'll utilize the preg match function and a regular expression for this extraction.
if (! preg_match('/Bearer\s(\S+)/', $_SERVER['HTTP_AUTHORIZATION'], $matches)){
header('HTTP/1.0 400 Bad Request');
echo 'Token not found in request';
exit;
}
The above code tries to get the token from the Bearer header. Error management is used in this scenario. If the token is not found, the user is presented with an HTTP 404 error.
To validate the JWT, you must compare it to the JWT that was previously produced.
$jwt = $matches[1]
if (! $jwt) {
// No token was able to be extracted from the authorization header
header('HTTP/1.0 400 Bad Request');
exit;
};
The extracted JWT is kept in the matches array at the first index. If the matched array is empty, this indicates that no JWT has been extracted. If the above code executes correctly, the JWT has been extracted, and you may proceed.
Verifying a JWT necessitates decoding the received data. The received data can only be decoded with the secret key. You may utilize the PHP-JWT module's static decode method once you've got the secret key.
The decode method takes the following three parameters.
If the decode method is successful, you may validate the JWT.
$secret_Key = 'ENTER_SECRET_KEY_HERE';
$token = JWT::decode($jwt, $secret_Key, ['HS512']);
$now = new DateTimeImmutable();
$serverName = "your.domain.name";
if ($token->iss !== $serverName ||
$token->nbf > $now->getTimestamp() ||
$token->exp < $now->getTimestamp())
{
header('HTTP/1.1 401 Unauthorized');
exit;
}
You learned about JWT in this article. Then, using PHP, We built a web application that was protected with JWT authentication. We realized how simple and crucial it is to protect a web application. Remember to use this method for your API Authentication.
Happy Learning :)
Développeur informatique
2 年Helle! Please, could you help me?
Lecturer at Usmanu Danfodiyo University, Sokoto
2 年thank you