Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove Config\App Security items #7630

Merged
merged 12 commits into from
Jun 29, 2023
85 changes: 0 additions & 85 deletions app/Config/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -158,91 +158,6 @@ class App extends BaseConfig
*/
public array $proxyIPs = [];

/**
* --------------------------------------------------------------------------
* CSRF Token Name
* --------------------------------------------------------------------------
*
* The token name.
*
* @deprecated Use `Config\Security` $tokenName property instead of using this property.
*/
public string $CSRFTokenName = 'csrf_test_name';

/**
* --------------------------------------------------------------------------
* CSRF Header Name
* --------------------------------------------------------------------------
*
* The header name.
*
* @deprecated Use `Config\Security` $headerName property instead of using this property.
*/
public string $CSRFHeaderName = 'X-CSRF-TOKEN';

/**
* --------------------------------------------------------------------------
* CSRF Cookie Name
* --------------------------------------------------------------------------
*
* The cookie name.
*
* @deprecated Use `Config\Security` $cookieName property instead of using this property.
*/
public string $CSRFCookieName = 'csrf_cookie_name';

/**
* --------------------------------------------------------------------------
* CSRF Expire
* --------------------------------------------------------------------------
*
* The number in seconds the token should expire.
*
* @deprecated Use `Config\Security` $expire property instead of using this property.
*/
public int $CSRFExpire = 7200;

/**
* --------------------------------------------------------------------------
* CSRF Regenerate
* --------------------------------------------------------------------------
*
* Regenerate token on every submission?
*
* @deprecated Use `Config\Security` $regenerate property instead of using this property.
*/
public bool $CSRFRegenerate = true;

/**
* --------------------------------------------------------------------------
* CSRF Redirect
* --------------------------------------------------------------------------
*
* Redirect to previous page with error on failure?
*
* @deprecated Use `Config\Security` $redirect property instead of using this property.
*/
public bool $CSRFRedirect = false;

/**
* --------------------------------------------------------------------------
* CSRF SameSite
* --------------------------------------------------------------------------
*
* Setting for CSRF SameSite cookie token. Allowed values are:
* - None
* - Lax
* - Strict
* - ''
*
* Defaults to `Lax` as recommended in this link:
*
* @see https://portswigger.net/web-security/csrf/samesite-cookies
*
* @deprecated `Config\Cookie` $samesite property is used.
*/
public string $CSRFSameSite = 'Lax';

/**
* --------------------------------------------------------------------------
* Content Security Policy
Expand Down
5 changes: 3 additions & 2 deletions system/Config/Services.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
use Config\Pager as PagerConfig;
use Config\Paths;
use Config\Routing;
use Config\Security as SecurityConfig;
use Config\Services as AppServices;
use Config\Session as SessionConfig;
use Config\Toolbar as ToolbarConfig;
Expand Down Expand Up @@ -627,13 +628,13 @@ public static function router(?RouteCollectionInterface $routes = null, ?Request
*
* @return Security
*/
public static function security(?App $config = null, bool $getShared = true)
public static function security(?SecurityConfig $config = null, bool $getShared = true)
{
if ($getShared) {
return static::getSharedInstance('security', $config);
}

$config ??= config(App::class);
$config ??= config(SecurityConfig::class);

return new Security($config);
}
Expand Down
86 changes: 43 additions & 43 deletions system/Security/Security.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
use CodeIgniter\I18n\Time;
use CodeIgniter\Security\Exceptions\SecurityException;
use CodeIgniter\Session\Session;
use Config\App;
use Config\Cookie as CookieConfig;
use Config\Security as SecurityConfig;
use Config\Services;
Expand All @@ -44,13 +43,17 @@ class Security implements SecurityInterface
* Protection Method for Cross Site Request Forgery protection.
*
* @var string 'cookie' or 'session'
*
* @deprecated 4.4.0 Use $this->config->csrfProtection.
michalsn marked this conversation as resolved.
Show resolved Hide resolved
*/
protected $csrfProtection = self::CSRF_PROTECTION_COOKIE;

/**
* CSRF Token Randomization
*
* @var bool
*
* @deprecated 4.4.0 Use $this->config->tokenRandomize.
*/
protected $tokenRandomize = false;

Expand All @@ -69,6 +72,8 @@ class Security implements SecurityInterface
* Token name for Cross Site Request Forgery protection.
*
* @var string
*
* @deprecated 4.4.0 Use $this->config->tokenName.
*/
protected $tokenName = 'csrf_token_name';

Expand All @@ -78,6 +83,8 @@ class Security implements SecurityInterface
* Header name for Cross Site Request Forgery protection.
*
* @var string
*
* @deprecated 4.4.0 Use $this->config->headerName.
*/
protected $headerName = 'X-CSRF-TOKEN';

Expand Down Expand Up @@ -105,6 +112,8 @@ class Security implements SecurityInterface
* Defaults to two hours (in seconds).
*
* @var int
*
* @deprecated 4.4.0 Use $this->config->expires.
*/
protected $expires = 7200;

Expand All @@ -114,6 +123,8 @@ class Security implements SecurityInterface
* Regenerate CSRF Token on every request.
*
* @var bool
*
* @deprecated 4.4.0 Use $this->config->regenerate.
*/
protected $regenerate = true;

Expand All @@ -123,6 +134,8 @@ class Security implements SecurityInterface
* Redirect to previous page with error on failure.
*
* @var bool
*
* @deprecated 4.4.0 Use $this->config->redirect.
*/
protected $redirect = false;

Expand Down Expand Up @@ -163,35 +176,22 @@ class Security implements SecurityInterface
*/
private ?string $hashInCookie = null;

/**
* Security Config
*/
protected SecurityConfig $config;

/**
* Constructor.
*
* Stores our configuration and fires off the init() method to setup
* initial state.
*/
public function __construct(App $config)
public function __construct(SecurityConfig $config)
{
$security = config(SecurityConfig::class);

// Store CSRF-related configurations
if ($security instanceof SecurityConfig) {
$this->csrfProtection = $security->csrfProtection ?? $this->csrfProtection;
$this->tokenName = $security->tokenName ?? $this->tokenName;
$this->headerName = $security->headerName ?? $this->headerName;
$this->regenerate = $security->regenerate ?? $this->regenerate;
$this->redirect = $security->redirect ?? $this->redirect;
$this->rawCookieName = $security->cookieName ?? $this->rawCookieName;
$this->expires = $security->expires ?? $this->expires;
$this->tokenRandomize = $security->tokenRandomize ?? $this->tokenRandomize;
michalsn marked this conversation as resolved.
Show resolved Hide resolved
} else {
// `Config/Security.php` is absence
$this->tokenName = $config->CSRFTokenName ?? $this->tokenName;
$this->headerName = $config->CSRFHeaderName ?? $this->headerName;
$this->regenerate = $config->CSRFRegenerate ?? $this->regenerate;
$this->rawCookieName = $config->CSRFCookieName ?? $this->rawCookieName;
$this->expires = $config->CSRFExpire ?? $this->expires;
$this->redirect = $config->CSRFRedirect ?? $this->redirect;
}
$this->config = $config;

$this->rawCookieName = $config->cookieName;

if ($this->isCSRFCookie()) {
$cookie = config(CookieConfig::class);
Expand All @@ -213,7 +213,7 @@ public function __construct(App $config)

private function isCSRFCookie(): bool
{
return $this->csrfProtection === self::CSRF_PROTECTION_COOKIE;
return $this->config->csrfProtection === self::CSRF_PROTECTION_COOKIE;
}

private function configureSession(): void
Expand Down Expand Up @@ -287,7 +287,7 @@ public function verify(RequestInterface $request)
$postedToken = $this->getPostedToken($request);

try {
$token = ($postedToken !== null && $this->tokenRandomize)
$token = ($postedToken !== null && $this->config->tokenRandomize)
? $this->derandomize($postedToken) : $postedToken;
} catch (InvalidArgumentException $e) {
$token = null;
Expand All @@ -300,7 +300,7 @@ public function verify(RequestInterface $request)

$this->removeTokenInRequest($request);

if ($this->regenerate) {
if ($this->config->regenerate) {
$this->generateHash();
}

Expand All @@ -318,13 +318,13 @@ private function removeTokenInRequest(RequestInterface $request): void

$json = json_decode($request->getBody() ?? '');

if (isset($_POST[$this->tokenName])) {
if (isset($_POST[$this->config->tokenName])) {
// We kill this since we're done and we don't want to pollute the POST array.
unset($_POST[$this->tokenName]);
unset($_POST[$this->config->tokenName]);
$request->setGlobal('post', $_POST);
} elseif (isset($json->{$this->tokenName})) {
} elseif (isset($json->{$this->config->tokenName})) {
// We kill this since we're done and we don't want to pollute the JSON data.
unset($json->{$this->tokenName});
unset($json->{$this->config->tokenName});
$request->setBody(json_encode($json));
}
}
Expand All @@ -335,19 +335,19 @@ private function getPostedToken(RequestInterface $request): ?string

// Does the token exist in POST, HEADER or optionally php:://input - json data.

if ($tokenValue = $request->getPost($this->tokenName)) {
if ($tokenValue = $request->getPost($this->config->tokenName)) {
return $tokenValue;
}

if ($request->hasHeader($this->headerName) && ! empty($request->header($this->headerName)->getValue())) {
return $request->header($this->headerName)->getValue();
if ($request->hasHeader($this->config->headerName) && ! empty($request->header($this->config->headerName)->getValue())) {
return $request->header($this->config->headerName)->getValue();
}

$body = (string) $request->getBody();
$json = json_decode($body);

if ($body !== '' && ! empty($json) && json_last_error() === JSON_ERROR_NONE) {
return $json->{$this->tokenName} ?? null;
return $json->{$this->config->tokenName} ?? null;
}

return null;
Expand All @@ -358,7 +358,7 @@ private function getPostedToken(RequestInterface $request): ?string
*/
public function getHash(): ?string
{
return $this->tokenRandomize ? $this->randomize($this->hash) : $this->hash;
return $this->config->tokenRandomize ? $this->randomize($this->hash) : $this->hash;
}

/**
Expand Down Expand Up @@ -407,23 +407,23 @@ protected function derandomize(string $token): string
*/
public function getTokenName(): string
{
return $this->tokenName;
return $this->config->tokenName;
}

/**
* Returns the CSRF Header Name.
*/
public function getHeaderName(): string
{
return $this->headerName;
return $this->config->headerName;
}

/**
* Returns the CSRF Cookie Name.
*/
public function getCookieName(): string
{
return $this->cookieName;
return $this->config->cookieName;
}

/**
Expand All @@ -443,7 +443,7 @@ public function isExpired(): bool
*/
public function shouldRedirect(): bool
{
return $this->redirect;
return $this->config->redirect;
}

/**
Expand Down Expand Up @@ -521,9 +521,9 @@ private function restoreHash(): void
if ($this->isHashInCookie()) {
$this->hash = $this->hashInCookie;
}
} elseif ($this->session->has($this->tokenName)) {
} elseif ($this->session->has($this->config->tokenName)) {
// Session based CSRF protection
$this->hash = $this->session->get($this->tokenName);
$this->hash = $this->session->get($this->config->tokenName);
}
}

Expand Down Expand Up @@ -562,7 +562,7 @@ private function saveHashInCookie(): void
$this->rawCookieName,
$this->hash,
[
'expires' => $this->expires === 0 ? 0 : Time::now()->getTimestamp() + $this->expires,
'expires' => $this->config->expires === 0 ? 0 : Time::now()->getTimestamp() + $this->config->expires,
]
);

Expand Down Expand Up @@ -606,6 +606,6 @@ protected function doSendCookie(): void

private function saveHashInSession(): void
{
$this->session->set($this->tokenName, $this->hash);
$this->session->set($this->config->tokenName, $this->hash);
}
}
8 changes: 0 additions & 8 deletions system/Test/Mock/MockAppConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,6 @@ class MockAppConfig extends App
public string $baseURL = 'http://example.com/';
public string $uriProtocol = 'REQUEST_URI';
public array $proxyIPs = [];
public string $CSRFTokenName = 'csrf_test_name';
public string $CSRFHeaderName = 'X-CSRF-TOKEN';
public string $CSRFCookieName = 'csrf_cookie_name';
public int $CSRFExpire = 7200;
public bool $CSRFRegenerate = true;
public array $CSRFExcludeURIs = ['http://example.com'];
public bool $CSRFRedirect = false;
public string $CSRFSameSite = 'Lax';
public bool $CSPEnabled = false;
public string $defaultLocale = 'en';
public bool $negotiateLocale = false;
Expand Down
Loading