Skip to content

Commit

Permalink
#129: Add Request Method to Protect endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
nicumicle committed Feb 22, 2025
1 parent c491db9 commit f46eba9
Show file tree
Hide file tree
Showing 11 changed files with 1,803 additions and 45 deletions.
3 changes: 3 additions & 0 deletions simple-jwt-login/js/scripts.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ jQuery(document).ready(
tempJWTLoginCopyInput = null;
}
);
// $('.multiple-checkboxes').multiselect({
// includeSelectAllOption: true,
// });

$('#simple-jwt-login #toggleHooks').on(
'click',
Expand Down
2 changes: 1 addition & 1 deletion simple-jwt-login/routes/api.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@

$documentRoot = esc_html($_SERVER['DOCUMENT_ROOT']);

$hasAccess = $service->hasAccess($currentURL, $documentRoot, $request);
$hasAccess = $service->hasAccess($_SERVER['REQUEST_METHOD'], $currentURL, $documentRoot, $request);

if ($hasAccess === false) {
@header('Content-Type: application/json; charset=UTF-8');
Expand Down
2 changes: 1 addition & 1 deletion simple-jwt-login/simple-jwt-login.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ function simple_jwt_login_plugin_show_main_page()
$pluginVersion = isset($pluginData['Version'])
? $pluginData['Version']
: false;
$pluginData = random_int(1, 1000000);
$pluginDirUrl = plugin_dir_url(__FILE__);
$loadScriptsInFooter = false;
wp_enqueue_style(
Expand Down Expand Up @@ -116,7 +117,6 @@ function simple_jwt_login_plugin_show_main_page()
$loadScriptsInFooter
);


require_once('views/layout.php');
}

Expand Down
63 changes: 52 additions & 11 deletions simple-jwt-login/src/Modules/Settings/ProtectEndpointSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ class ProtectEndpointSettings extends BaseSettings implements SettingsInterface
const ALL_ENDPOINTS = 1;
const SPECIFIC_ENDPOINTS = 2;

public const ALL_REQUEST_METHOD = 'ALL';

public function initSettingsFromPost()
{
$this->assignSettingsPropertyFromPost(
Expand All @@ -34,13 +36,27 @@ public function initSettingsFromPost()
'protect',
BaseSettings::SETTINGS_TYPE_ARRAY
);
$this->assignSettingsPropertyFromPost(
self::PROPERTY_GROUP,
'protect_method',
self::PROPERTY_GROUP,
'protect_method',
BaseSettings::SETTINGS_TYPE_ARRAY
);
$this->assignSettingsPropertyFromPost(
self::PROPERTY_GROUP,
'whitelist',
self::PROPERTY_GROUP,
'whitelist',
BaseSettings::SETTINGS_TYPE_ARRAY
);
$this->assignSettingsPropertyFromPost(
self::PROPERTY_GROUP,
'whitelist_method',
self::PROPERTY_GROUP,
'whitelist_method',
BaseSettings::SETTINGS_TYPE_ARRAY
);
}

public function validateSettings()
Expand All @@ -50,7 +66,7 @@ public function validateSettings()
}

$filteredEndpoints = array_filter($this->getProtectedEndpoints(), function ($value) {
return !empty(trim($value));
return !empty(trim($value['url'], " "));
});

if ($this->getAction() === ProtectEndpointSettings::SPECIFIC_ENDPOINTS && empty($filteredEndpoints)) {
Expand Down Expand Up @@ -83,26 +99,51 @@ public function getAction()
}

/**
* @return string[]
* @return array<int,array<string,mixed>>
*/
public function getWhitelistedDomains()
{
$result = isset($this->settings[ProtectEndpointSettings::PROPERTY_GROUP]['whitelist'])
? (array) $this->settings[ProtectEndpointSettings::PROPERTY_GROUP]['whitelist']
: [''];

return array_unique($result);
return $this->parseProtectSettings('whitelist_method', 'whitelist');
}

/**
* @return string[]
* @return array<int,array<string,mixed>>
*/
public function getProtectedEndpoints()
{
$result = isset($this->settings[ProtectEndpointSettings::PROPERTY_GROUP]['protect'])
? (array) $this->settings[ProtectEndpointSettings::PROPERTY_GROUP]['protect']
return $this->parseProtectSettings('protect_method', 'protect');
}

/**
* @param string $methodKey
* @param string $endpointsKey
* @return array<int,array<string,mixed>>
*/
private function parseProtectSettings($methodKey, $endpointsKey)
{
$endpoints = isset($this->settings[ProtectEndpointSettings::PROPERTY_GROUP][$endpointsKey])
? (array) $this->settings[ProtectEndpointSettings::PROPERTY_GROUP][$endpointsKey]
: [''];
$methods = isset($this->settings[ProtectEndpointSettings::PROPERTY_GROUP][$methodKey])
? (array) $this->settings[ProtectEndpointSettings::PROPERTY_GROUP][$methodKey]
: [''];

$return = [];
foreach ($endpoints as $key => $endpointPath) {
$return[] = [
'url' => $endpointPath,
'method' => !empty($methods[$key])
? strtoupper($methods[$key])
: self::ALL_REQUEST_METHOD,
];
}

return array_unique($result);
return array_values(array_filter($return, function ($endpoint) {
if (trim($endpoint['url']) === "") {
return false;
};

return true;
}));
}
}
33 changes: 24 additions & 9 deletions simple-jwt-login/src/Services/ProtectEndpointService.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@ public function withRouteService($routeService)
}

/**
* @param string $requestMethod
* @param string $currentUrl
* @param string $documentRoot
* @param array $request
*
* @throws Exception
* @return bool
*/
public function hasAccess($currentUrl, $documentRoot, $request)
public function hasAccess($requestMethod, $currentUrl, $documentRoot, $request)
{
if ($this->jwtSettings->getProtectEndpointsSettings()->isEnabled() === false) {
return true;
Expand All @@ -45,10 +46,10 @@ public function hasAccess($currentUrl, $documentRoot, $request)

$isEndpointsProtected = true;
if (!empty(trim($path, '/'))) {
$isEndpointsProtected = $this->isEndpointProtected($path);
$isEndpointsProtected = $this->isEndpointProtected($requestMethod, $path);
}
if (!empty($request['rest_route'])) {
$isEndpointsProtected = $this->isEndpointProtected($request['rest_route']);
$isEndpointsProtected = $this->isEndpointProtected($requestMethod, $request['rest_route']);
}
if ($isEndpointsProtected === false) {
return true;
Expand Down Expand Up @@ -80,10 +81,11 @@ public function hasAccess($currentUrl, $documentRoot, $request)
}

/**
* @param string $requestMethod
* @param string $endpoint
* @return bool
*/
private function isEndpointProtected($endpoint)
private function isEndpointProtected($requestMethod, $endpoint)
{
if (strpos($endpoint, '/') !== 0) {
$endpoint = '/' . $endpoint;
Expand All @@ -109,13 +111,15 @@ private function isEndpointProtected($endpoint)
switch ($action) {
case ProtectEndpointSettings::ALL_ENDPOINTS:
return $this->parseDomainsAndGetResult(
$requestMethod,
$endpoint,
$protectSettings->getWhitelistedDomains(),
true,
false
);
case ProtectEndpointSettings::SPECIFIC_ENDPOINTS:
return $this->parseDomainsAndGetResult(
$requestMethod,
$endpoint,
$protectSettings->getProtectedEndpoints(),
false,
Expand All @@ -127,23 +131,34 @@ private function isEndpointProtected($endpoint)
}

/**
* @param string $requestMethod
* @param string $endpoint
* @param array $domains
* @param bool $defaultValue
* @param bool $setValue
* @return bool
*/
private function parseDomainsAndGetResult($endpoint, $domains, $defaultValue, $setValue)
private function parseDomainsAndGetResult($requestMethod, $endpoint, $domains, $defaultValue, $setValue)
{
$isEndpointProtected = $defaultValue;
foreach ($domains as $protectedEndpoint) {
$protectedEndpoint = $this->removeWpJsonFromEndpoint($protectedEndpoint);
$protectedURL = $this->removeWpJsonFromEndpoint($protectedEndpoint['url']);
$endpoint = $this->removeWpJsonFromEndpoint($endpoint);
if (empty(trim($protectedEndpoint, '/'))) {
if (empty(trim($protectedURL, '/'))) {
continue;
}
if (strpos($endpoint, $protectedEndpoint) === 0) {
$isEndpointProtected = $setValue;

if (strpos($endpoint, $protectedURL) === 0) {
switch ($protectedEndpoint['method']) {
case 'ALL':
$isEndpointProtected = $setValue; // Same as before.
break;
default:
if ($protectedEndpoint['method'] === $requestMethod) {
$isEndpointProtected = $setValue;
}
break;
}
}
}

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit f46eba9

Please sign in to comment.