In order to construct a secure resource that can be accessed through an API, we must utilize an authorization header with a token or bearer. In this article, I will guide you how to obtain the authorization header, extract the token or bearer. Then authenticate it against a database table and return a JSON output in PHP.
Here is what I have on my system.
- PHP 8.1
- Apache
- MariaDB 10.6
- Manjaro OS
PHP already has a built-in function, getallheaders(), that can retrieve all headers. It is useful because it eliminates the need for additional code to be written.
$headers = getallheaders();
The next step is to check if the key exists in the array. We will use the array_key_exists
function. If it does not exist, return an error.
if (!array_key_exists('Authorization', $headers)) {
echo json_encode(["error" => "Authorization header is missing"]);
exit;
}
In most cases, the token has a keyword of your choice, such as ‘Token‘ or ‘Bearer‘. To check this, we will use the substr function.
For Token:
if (substr($headers['Authorization'], 0, 6) !== 'Token ') {
echo json_encode(["error" => "Token keyword is missing"]);
exit;
}
For Bearer:
if (substr($headers['Authorization'], 0, 7) !== 'Bearer ') {
echo json_encode(["error" => "Bearer keyword is missing"]);
exit;
}
Now we will extract the actual token. This is for Token keyword.
$token = trim(substr($headers['Authorization'], 6));
We will also need to check the validity of the token against a database table. I am using my own framework for this purpose, but you can also accomplish this by connecting to the database and running a query similar to the following:
$host = "host";
$dbname = "database";
$username = "username";
$password = "password";
$conn = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$query = "SELECT
COUNT(t.token) as totalRows
FROM tokens as t
WHERE t.token = :token";
$data = [
"token" => $token
];
$stmt = $conn->prepare($query);
$stmt->execute($data);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
$count = $result['totalRows'];
Full code
$host = "host";
$dbname = "database";
$username = "username";
$password = "password";
$conn = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$headers = getallheaders();
if (!array_key_exists('Authorization', $headers)) {
echo json_encode(["error" => "Authorization header is missing"]);
exit;
}
else {
if (substr($headers['Authorization'], 0, 6) !== 'Token ') {
echo json_encode(["error" => "Token keyword is missing"]);
exit;
}
else {
$token = trim(substr($headers['Authorization'], 6));
$query = "SELECT
COUNT(t.token) as totalRows
FROM tokens as t
WHERE t.token = :token";
$data = [
"token" => $token
];
$stmt = $conn->prepare($query);
$stmt->execute($data);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
$count = $result['totalRows'];
if ($count == 0) {
echo json_encode(["error" => "Authorization failed"]);
exit;
}
else {
## continue the rest of your stuff
}
}
}
If you are using Bearer keyword, remember to change the position to 7 in substr function.
Something like this will work.
$token = trim(substr($headers['Authorization'], 7));