Skip to content

Commit d208002

Browse files
committed
API key support
1 parent bbffde5 commit d208002

File tree

2 files changed

+204
-232
lines changed

2 files changed

+204
-232
lines changed

api.include.php

Lines changed: 102 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -7287,6 +7287,100 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
72877287
}
72887288
}
72897289

7290+
// file: src/Tqdev/PhpCrudApi/Middleware/ApiKeyAuthMiddleware.php
7291+
namespace Tqdev\PhpCrudApi\Middleware {
7292+
7293+
use Psr\Http\Message\ResponseInterface;
7294+
use Psr\Http\Message\ServerRequestInterface;
7295+
use Psr\Http\Server\RequestHandlerInterface;
7296+
use Tqdev\PhpCrudApi\Controller\Responder;
7297+
use Tqdev\PhpCrudApi\Middleware\Base\Middleware;
7298+
use Tqdev\PhpCrudApi\Record\ErrorCode;
7299+
use Tqdev\PhpCrudApi\RequestUtils;
7300+
7301+
class ApiKeyAuthMiddleware extends Middleware
7302+
{
7303+
public function process(ServerRequestInterface $request, RequestHandlerInterface $next): ResponseInterface
7304+
{
7305+
$headerName = $this->getProperty('header', 'X-API-Key');
7306+
$apiKey = RequestUtils::getHeader($request, $headerName);
7307+
if ($apiKey) {
7308+
$apiKeys = $this->getArrayProperty('keys', '');
7309+
if (!in_array($apiKey, $apiKeys)) {
7310+
return $this->responder->error(ErrorCode::AUTHENTICATION_FAILED, $apiKey);
7311+
}
7312+
} else {
7313+
$authenticationMode = $this->getProperty('mode', 'required');
7314+
if ($authenticationMode == 'required') {
7315+
return $this->responder->error(ErrorCode::AUTHENTICATION_REQUIRED, '');
7316+
}
7317+
}
7318+
$_SESSION['apiKey'] = $apiKey;
7319+
return $next->handle($request);
7320+
}
7321+
}
7322+
}
7323+
7324+
// file: src/Tqdev/PhpCrudApi/Middleware/ApiKeyDbAuthMiddleware.php
7325+
namespace Tqdev\PhpCrudApi\Middleware {
7326+
7327+
use Psr\Http\Message\ResponseInterface;
7328+
use Psr\Http\Message\ServerRequestInterface;
7329+
use Psr\Http\Server\RequestHandlerInterface;
7330+
use Tqdev\PhpCrudApi\Column\ReflectionService;
7331+
use Tqdev\PhpCrudApi\Controller\Responder;
7332+
use Tqdev\PhpCrudApi\Database\GenericDB;
7333+
use Tqdev\PhpCrudApi\Middleware\Base\Middleware;
7334+
use Tqdev\PhpCrudApi\Middleware\Router\Router;
7335+
use Tqdev\PhpCrudApi\Record\Condition\ColumnCondition;
7336+
use Tqdev\PhpCrudApi\Record\ErrorCode;
7337+
use Tqdev\PhpCrudApi\Record\OrderingInfo;
7338+
use Tqdev\PhpCrudApi\RequestUtils;
7339+
7340+
class ApiKeyDbAuthMiddleware extends Middleware
7341+
{
7342+
private $reflection;
7343+
private $db;
7344+
private $ordering;
7345+
7346+
public function __construct(Router $router, Responder $responder, array $properties, ReflectionService $reflection, GenericDB $db)
7347+
{
7348+
parent::__construct($router, $responder, $properties);
7349+
$this->reflection = $reflection;
7350+
$this->db = $db;
7351+
$this->ordering = new OrderingInfo();
7352+
}
7353+
7354+
public function process(ServerRequestInterface $request, RequestHandlerInterface $next): ResponseInterface
7355+
{
7356+
$user = false;
7357+
$headerName = $this->getProperty('header', 'X-API-Key');
7358+
$apiKey = RequestUtils::getHeader($request, $headerName);
7359+
if ($apiKey) {
7360+
$tableName = $this->getProperty('usersTable', 'users');
7361+
$table = $this->reflection->getTable($tableName);
7362+
$apiKeyColumnName = $this->getProperty('apiKeyColumn', 'api_key');
7363+
$apiKeyColumn = $table->getColumn($apiKeyColumnName);
7364+
$condition = new ColumnCondition($apiKeyColumn, 'eq', $apiKey);
7365+
$columnNames = $table->getColumnNames();
7366+
$columnOrdering = $this->ordering->getDefaultColumnOrdering($table);
7367+
$users = $this->db->selectAll($table, $columnNames, $condition, $columnOrdering, 0, 1);
7368+
if (count($users) < 1) {
7369+
return $this->responder->error(ErrorCode::AUTHENTICATION_FAILED, $apiKey);
7370+
}
7371+
$user = $users[0];
7372+
} else {
7373+
$authenticationMode = $this->getProperty('mode', 'required');
7374+
if ($authenticationMode == 'required') {
7375+
return $this->responder->error(ErrorCode::AUTHENTICATION_REQUIRED, '');
7376+
}
7377+
}
7378+
$_SESSION['apiUser'] = $user;
7379+
return $next->handle($request);
7380+
}
7381+
}
7382+
}
7383+
72907384
// file: src/Tqdev/PhpCrudApi/Middleware/AuthorizationMiddleware.php
72917385
namespace Tqdev\PhpCrudApi\Middleware {
72927386

@@ -8394,122 +8488,6 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
83948488
}
83958489
}
83968490

8397-
// file: src/Tqdev/PhpCrudApi/Middleware/QueryQuotaMiddleware.php
8398-
namespace Tqdev\PhpCrudApi\Middleware {
8399-
8400-
use Psr\Http\Message\ResponseInterface;
8401-
use Psr\Http\Message\ServerRequestInterface;
8402-
use Psr\Http\Server\RequestHandlerInterface;
8403-
use Tqdev\PhpCrudApi\Controller\Responder;
8404-
use Tqdev\PhpCrudApi\Middleware\Base\Middleware;
8405-
use Tqdev\PhpCrudApi\Record\ErrorCode;
8406-
8407-
class QueryQuotaMiddleware extends Middleware
8408-
{
8409-
private function ipMatch(string $ip, string $cidr): bool
8410-
{
8411-
if (strpos($cidr, '/') !== false) {
8412-
list($subnet, $mask) = explode('/', trim($cidr));
8413-
if ((ip2long($ip) & ~((1 << (32 - $mask)) - 1)) == ip2long($subnet)) {
8414-
return true;
8415-
}
8416-
} else {
8417-
if (ip2long($ip) == ip2long($cidr)) {
8418-
return true;
8419-
}
8420-
}
8421-
return false;
8422-
}
8423-
8424-
private function isIpAllowed(string $ipAddress, string $allowedIpAddresses): bool
8425-
{
8426-
foreach (explode(',', $allowedIpAddresses) as $allowedIp) {
8427-
if ($this->ipMatch($ipAddress, $allowedIp)) {
8428-
return true;
8429-
}
8430-
}
8431-
return false;
8432-
}
8433-
8434-
public function process(ServerRequestInterface $request, RequestHandlerInterface $next): ResponseInterface
8435-
{
8436-
$reverseProxy = $this->getProperty('reverseProxy', '');
8437-
if ($reverseProxy) {
8438-
$ipAddress = array_pop(explode(',', $request->getHeader('X-Forwarded-For')));
8439-
} elseif (isset($_SERVER['REMOTE_ADDR'])) {
8440-
$ipAddress = $_SERVER['REMOTE_ADDR'];
8441-
} else {
8442-
$ipAddress = '127.0.0.1';
8443-
}
8444-
$allowedIpAddresses = $this->getProperty('allowedIpAddresses', '');
8445-
if (!$this->isIpAllowed($ipAddress, $allowedIpAddresses)) {
8446-
$response = $this->responder->error(ErrorCode::TEMPORARY_OR_PERMANENTLY_BLOCKED, '');
8447-
} else {
8448-
$response = $next->handle($request);
8449-
}
8450-
return $response;
8451-
}
8452-
}
8453-
}
8454-
8455-
// file: src/Tqdev/PhpCrudApi/Middleware/RateLimitMiddleware copy.php
8456-
namespace Tqdev\PhpCrudApi\Middleware {
8457-
8458-
use Psr\Http\Message\ResponseInterface;
8459-
use Psr\Http\Message\ServerRequestInterface;
8460-
use Psr\Http\Server\RequestHandlerInterface;
8461-
use Tqdev\PhpCrudApi\Controller\Responder;
8462-
use Tqdev\PhpCrudApi\Middleware\Base\Middleware;
8463-
use Tqdev\PhpCrudApi\Record\ErrorCode;
8464-
8465-
class RateLimitMiddleware extends Middleware
8466-
{
8467-
private function ipMatch(string $ip, string $cidr): bool
8468-
{
8469-
if (strpos($cidr, '/') !== false) {
8470-
list($subnet, $mask) = explode('/', trim($cidr));
8471-
if ((ip2long($ip) & ~((1 << (32 - $mask)) - 1)) == ip2long($subnet)) {
8472-
return true;
8473-
}
8474-
} else {
8475-
if (ip2long($ip) == ip2long($cidr)) {
8476-
return true;
8477-
}
8478-
}
8479-
return false;
8480-
}
8481-
8482-
private function isIpAllowed(string $ipAddress, string $allowedIpAddresses): bool
8483-
{
8484-
foreach (explode(',', $allowedIpAddresses) as $allowedIp) {
8485-
if ($this->ipMatch($ipAddress, $allowedIp)) {
8486-
return true;
8487-
}
8488-
}
8489-
return false;
8490-
}
8491-
8492-
public function process(ServerRequestInterface $request, RequestHandlerInterface $next): ResponseInterface
8493-
{
8494-
$reverseProxy = $this->getProperty('reverseProxy', '');
8495-
if ($reverseProxy) {
8496-
$ipAddress = array_pop(explode(',', $request->getHeader('X-Forwarded-For')));
8497-
} elseif (isset($_SERVER['REMOTE_ADDR'])) {
8498-
$ipAddress = $_SERVER['REMOTE_ADDR'];
8499-
} else {
8500-
$ipAddress = '127.0.0.1';
8501-
}
8502-
$allowedIpAddresses = $this->getProperty('allowedIpAddresses', '');
8503-
if (!$this->isIpAllowed($ipAddress, $allowedIpAddresses)) {
8504-
$response = $this->responder->error(ErrorCode::TEMPORARY_OR_PERMANENTLY_BLOCKED, '');
8505-
} else {
8506-
$response = $next->handle($request);
8507-
}
8508-
return $response;
8509-
}
8510-
}
8511-
}
8512-
85138491
// file: src/Tqdev/PhpCrudApi/Middleware/ReconnectMiddleware.php
85148492
namespace Tqdev\PhpCrudApi\Middleware {
85158493

@@ -11216,6 +11194,8 @@ private function setHabtmValues(ReflectedTable $t1, ReflectedTable $t2, array &$
1121611194
use Tqdev\PhpCrudApi\Controller\StatusController;
1121711195
use Tqdev\PhpCrudApi\Database\GenericDB;
1121811196
use Tqdev\PhpCrudApi\GeoJson\GeoJsonService;
11197+
use Tqdev\PhpCrudApi\Middleware\ApiKeyAuthMiddleware;
11198+
use Tqdev\PhpCrudApi\Middleware\ApiKeyDbAuthMiddleware;
1121911199
use Tqdev\PhpCrudApi\Middleware\AuthorizationMiddleware;
1122011200
use Tqdev\PhpCrudApi\Middleware\BasicAuthMiddleware;
1122111201
use Tqdev\PhpCrudApi\Middleware\CorsMiddleware;
@@ -11273,6 +11253,12 @@ public function __construct(Config $config)
1127311253
case 'firewall':
1127411254
new FirewallMiddleware($router, $responder, $properties);
1127511255
break;
11256+
case 'apiKeyAuth':
11257+
new ApiKeyAuthMiddleware($router, $responder, $properties);
11258+
break;
11259+
case 'apiKeyDbAuth':
11260+
new ApiKeyDbAuthMiddleware($router, $responder, $properties, $reflection, $db);
11261+
break;
1127611262
case 'basicAuth':
1127711263
new BasicAuthMiddleware($router, $responder, $properties);
1127811264
break;

0 commit comments

Comments
 (0)