Introduction
We already seen REST API development tutorial, now we are going to implement Secure PHP REST API with JWT authentication. We can covering Securing end-points using JSON Web Tokens (JWT) and make it API more scalable, Robust and efficient.
Why Use of JWT Authentication?
JWT Authentication is Stateless, Scalable, Secure and better for Performance Optimization. Here are key point :
Stateless communication : Not store any data in any form like SESSION, COOKIE.
Security : Protect again CSRF injections.
Performance : Faster Authentication, without look up DATABASE
Implementation Prerequisites
- PHP 7+ Installed with enable CURL extension.
- Install Composer.
- Web Server like APACHE, Nginx or built-in PHP server
Code Implementation Guide
Download and install Firebase PHP-JWT (JSON Web Tokens) library from GitHub, which can helps for generating web token.
composer require firebase/php-jwt
Create Database Connection db.php
<?php $host = "127.0.0.1:3360"; $db_name = "new_programmerdesk"; $username = "root"; $password = ""; $conn = new mysqli($host, $username, $password, $db_name); if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error); } ?>
Create JWT Authentication Function
Create jwt.php file where we can Manage JWT Token
iss
– Issuer use for Identifies the token source, you can put on your domain name.iat
– Issued at – Existing timestamp of creationexp
– Expiration – Set token expire time.
Here is complete guide for JSON Web Token
<?php require 'vendor/autoload.php'; use Firebase\JWT\JWT; use Firebase\JWT\Key; //echo $secret_key = base64_encode(random_bytes(32)); $secret_key = "yuSwN0wsV9QLJ6J3Y5R3JXepeIi214YGMLCXFb2aF84"; function createJWT($user_id, $role, $exp_time = 900) { global $secret_key; $payload = [ "iss" => "localhost\programmerdesk\tutorial\new\php\php-jwt-auth", "iat" => time(), "exp" => time() + $exp_time, "user_id" => $user_id, "role" => $role ]; return JWT::encode($payload, $secret_key, 'HS256'); } function verifyJWT($token) { global $secret_key; try { return JWT::decode($token, new Key($secret_key, 'HS256')); } catch (Exception $e) { return false; } } function getBearerToken() { $headers = getallheaders(); if (!isset($headers['Authorization'])) { return null; } $authHeader = explode(" ", $headers['Authorization']); return $authHeader[1] ?? null; } ?>
Implement User Authentication and Token
Create file login.php for implementing login functionality and set Token expiry and refresh using setcookie
<?php require 'db.php'; require 'jwt.php'; $data = json_decode(file_get_contents("php://input"), true); $stmt = $conn->prepare("SELECT id, password, role FROM users_jwt_auth WHERE email=?"); $stmt->bind_param("s", $data['email']); $stmt->execute(); $result = $stmt->get_result()->fetch_assoc(); if ($result && password_verify($data['password'], $result['password'])) { $access_token = createJWT($result['id'], $result['role'], 900); // 15 min expiry $refresh_token = createJWT($result['id'], $result['role'], 86400); // 24 hr expiry setcookie("refresh_token", $refresh_token, [ "httponly" => true, "secure" => true, "samesite" => "Strict" ]); echo json_encode(["access_token" => $access_token]); } else { echo json_encode(["error" => "Invalid credentials"]); } ?>
Working Process of login.php
- Validate Email and Password.
- If exists generate JWT token else display invalid credentials.
- Generate JWT token using createJWT function from jwt.php file.
- Return JWT token as response.
Implement User Registration
Create register.php file and request for name, email and password. Simply insert user data using postman for later use.
<?php require 'db.php'; $data = json_decode(file_get_contents("php://input"), true); if (!empty($data['name']) && !empty($data['email']) && !empty($data['password'])) { $hashed_password = password_hash($data['password'], PASSWORD_DEFAULT); $stmt = $conn->prepare("INSERT INTO users_jwt_auth (name, email, password) VALUES (?, ?, ?)"); $stmt->bind_param("sss", $data['name'], $data['email'], $hashed_password); if ($stmt->execute()) { echo json_encode(["message" => "User registered successfully"]); } else { echo json_encode(["error" => "Email already exists"]); } } else { echo json_encode(["error" => "Missing parameters"]); } ?>
Display All users data.
Create users.php file with pass token which generated by login.php
<?php require 'db.php'; require 'jwt.php'; $token = getBearerToken(); $decoded = verifyJWT($token); if (!$decoded) { echo json_encode(["error" => "Unauthorized"]); http_response_code(401); exit; } $stmt = $conn->prepare("SELECT id, name, email FROM users"); $stmt->execute(); $result = $stmt->get_result()->fetch_all(MYSQLI_ASSOC); echo json_encode($result); ?>
Implement Refresh token
Create refresh.php file for refresh token. if token is expire then generate new one.
<?php require 'jwt.php'; if (!isset($_COOKIE['refresh_token'])) { echo json_encode(["error" => "No refresh token found"]); exit; } $decoded = verifyJWT($_COOKIE['refresh_token']); if (!$decoded) { echo json_encode(["error" => "Invalid refresh token"]); exit; } $new_access_token = createJWT($decoded->user_id, $decoded->role, 900); echo json_encode(["access_token" => $new_access_token]); ?>
Implement logout functionality.
Create logout.php file and insert into blacklisted_tokens table.
<?php require 'db.php'; require 'jwt.php'; $token = getBearerToken(); if (!$token) { echo json_encode(["error" => "No token provided"]); exit; } $stmt = $conn->prepare("INSERT INTO blacklisted_tokens (token) VALUES (?)"); $stmt->bind_param("s", $token); $stmt->execute(); setcookie("refresh_token", "", time() - 3600, "/"); echo json_encode(["message" => "Logged out successfully"]); ?>
Testing API Request with the Token
- Registration User.
//registration curl -X GET http://localhost/register.php

- Login User
curl -X POST http://localhost/login.php

- Retrieve all users
After login done, access users data with use Authorization
header
curl -H "Authorization: Bearer YOUR_GENERATED_TOKEN" localhost/users.php

Security Enhancement
- Always use HTTPS for secure transmission data.
- Always use Token Refresh Mechanism for Prevent session hijacking
- Secure Database for prevent SQL injection, always use prepared statements
FAQ
What is JWT authentication in PHP?
JWT Authentication securely transmitted JSON data from Server to client. JWT authentication stores public/private key pairs for exchanging information.
How do JSON Web Tokens Works?
After successfully, login using user credentials. In Response JSON OBJECT Return.
Authorization: Bearer <token>
use for accessing secure routing or protected data.
How to refresh an expired JWT token?
User can refresh use refresh token mechanism to call them and regenerate new token.
Conclusion
We have implement JWT token based authentication system with follow best security practices and stateless authentication.