I'm currently writing an API in PHP which uses a JWT for authentication, and I'm running into a strange issue in my try-catch
blocks. If I pass in no JWT or a malformed JWT with my HTTP request, my serverside code will throw an exception as expected and then execute code in the relevant catch
block, sending back a 401: Access Denied
response. However, the sever appears to then continue execution of the remaining code in the try
block, executing a SQL query and sending the results as if nothing had happened.
Here's an excerpt of my code:
try {
$decoded = JWT::decode($jwt, $access_key, array('HS256')); // Exception thrown here
...
setResponseCode(200);
echo json_encode($results);
} catch (Exception $e) {
setResponseCode(401, "Access denied: " . $e->getMessage());
}
As far as I can tell, this is the order of events: First an exception is thrown at the first line in the try
block. Then the code in the catch
block executes. Then the remaining code in the try
block executes.
This is obviously a huge security flaw, but I can't figure out why it might be happening. What exactly is going on?
EDIT: Additional context
This is the only code in the PHP file that sits above the try-catch
block, and no code exists below it. I don't see how it would be likely to interfere with the try-catch block.
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: GET");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
include_once 'config/core.php';
use Firebase\JWT\JWT;
foreach (getallheaders() as $name => $value) {
if (strcmp($name, "Authorization") == 0) {
$jwt = $value;
}
}
And this is how the API is being called from Javascript:
axios
.get(API_URL + "foo.php")
.then((response) => {
console.log(response.data.body);
})
.catch((error) => {
console.log(error.response.statusText);
});
Since no JWT is supplied, an error should be printing to the console. Instead, I get an automatic warning from the browser that my request received a 401 response, but then the object I requested prints out to the console as if I supplied correct authentication information.