Skip to content

Commit

Permalink
Merge branch 'release/1.1.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
adrenth committed Oct 9, 2019
2 parents 85a2f47 + 9acac9a commit 5aefabb
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 14 deletions.
22 changes: 17 additions & 5 deletions Plugin.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
<?php

/** @noinspection SpellCheckingInspection */
/** @noinspection PhpMissingParentCallCommonInspection */

declare(strict_types=1);

namespace Vdlp\Csrf;

use Cms\Classes\CmsController;
use System\Classes\PluginBase;
use Vdlp\Csrf\Middleware;
use Vdlp\Csrf\ServiceProviders;

/**
* Class Plugin
Expand All @@ -15,7 +20,7 @@
class Plugin extends PluginBase
{
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function pluginDetails(): array
{
Expand All @@ -28,19 +33,26 @@ public function pluginDetails(): array
];
}


/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function boot(): void
{
CmsController::extend(static function (CmsController $controller) {
$controller->middleware(VerifyCsrfTokenMiddleware::class);
$controller->middleware(Middleware\VerifyCsrfTokenMiddleware::class);
});
}

/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function register(): void
{
$this->app->register(ServiceProviders\CsrfServiceProvider::class);
}

/**
* {@inheritDoc}
*/
public function registerMarkupTags(): array
{
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ Go to Settings > Updates & Plugins > Install plugins and search for 'CSRF'.

## Configuration

Add the plugin configuration to your projects' config folder:

```
php artisan vendor:publish --provider="Vdlp\Csrf\ServiceProviders\CsrfServiceProvider" --tag="config"
```

Add the CSRF token to the head:

```
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vdlp/oc-csrf-plugin",
"description": "Adds CSRF protection to OctoberCMS frontend.",
"description": "Adds CSRF protection to October CMS frontend.",
"type": "october-plugin",
"license": "GPL-2.0",
"authors": [
Expand Down
20 changes: 20 additions & 0 deletions config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

return [

/*
|--------------------------------------------------------------------------
| Exclude Paths
|--------------------------------------------------------------------------
|
| Add paths to exclude CSRF token validation (not recommended).
|
*/

'exclude_paths' => [
// i.e. '/path/to/exclude'
],

];
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Vdlp\Csrf;
namespace Vdlp\Csrf\Middleware;

use Closure;
use Illuminate\Contracts\Encryption\Encrypter;
Expand All @@ -17,9 +17,9 @@
/**
* Class VerifyCsrfTokenMiddleware
*
* @package Vdlp\Csrf
* @package Vdlp\Csrf\Middleware
*/
class VerifyCsrfTokenMiddleware
final class VerifyCsrfTokenMiddleware
{
/**
* @var Encrypter
Expand All @@ -36,16 +36,27 @@ class VerifyCsrfTokenMiddleware
*/
private $responseFactory;

/**
* @var array
*/
private $excludePaths;

/**
* @param Encrypter $encrypter
* @param Redirector $redirector
* @param ResponseFactory $responseFactory
* @param array $excludePaths
*/
public function __construct(Encrypter $encrypter, Redirector $redirector, ResponseFactory $responseFactory)
{
public function __construct(
Encrypter $encrypter,
Redirector $redirector,
ResponseFactory $responseFactory,
array $excludePaths = []
) {
$this->encrypter = $encrypter;
$this->redirector = $redirector;
$this->responseFactory = $responseFactory;
$this->excludePaths = $excludePaths;
}

/**
Expand All @@ -56,7 +67,7 @@ public function __construct(Encrypter $encrypter, Redirector $redirector, Respon
*/
public function handle(Request $request, Closure $next)
{
if ($this->isReading($request) || $this->tokensMatch($request)) {
if ($this->isReading($request) || $this->excludePathMatch($request) || $this->tokensMatch($request)) {
return $next($request);
}

Expand All @@ -83,7 +94,7 @@ private function isReading($request): bool
* @return bool
* @throws RuntimeException
*/
private function tokensMatch($request): bool
private function tokensMatch(Request $request): bool
{
$token = $this->getTokenFromRequest($request);

Expand All @@ -92,13 +103,23 @@ private function tokensMatch($request): bool
&& hash_equals($request->session()->token(), $token);
}

/**
* @param Request $request
* @return bool
*/
private function excludePathMatch(Request $request): bool
{
return in_array($request->path(), $this->excludePaths, true);
}

/**
* @param Request $request
* @return string
*/
private function getTokenFromRequest($request): string
private function getTokenFromRequest(Request $request): string
{
$token = $request->input('_token') ?: $request->header('X-CSRF-TOKEN');

if (!$token && $header = $request->header('X-XSRF-TOKEN')) {
$token = $this->encrypter->decrypt($header, EncryptCookies::serialized('XSRF-TOKEN'));
}
Expand Down
52 changes: 52 additions & 0 deletions serviceproviders/CsrfServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

namespace Vdlp\Csrf\ServiceProviders;

use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Encryption\Encrypter;
use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Routing\Redirector;
use October\Rain\Support\ServiceProvider;
use Vdlp\Csrf\Middleware\VerifyCsrfTokenMiddleware;

/**
* Class CsrfServiceProvider
*
* @package Vdlp\Csrf\ServiceProviders
*/
final class CsrfServiceProvider extends ServiceProvider
{
/**
* @return void
*/
public function boot(): void
{
$this->publishes([
__DIR__ . '/../config.php' => config_path('csrf.php'),
], 'config');
}

/**
* @return void
*/
public function register(): void
{
$this->app->bind(
VerifyCsrfTokenMiddleware::class,
static function (Container $container): VerifyCsrfTokenMiddleware {
$excludePaths = array_map(static function (string $path): string {
return ltrim($path, '/');
}, config('csrf.exclude_paths', []));

return new VerifyCsrfTokenMiddleware(
$container->make(Encrypter::class),
$container->make(Redirector::class),
$container->make(ResponseFactory::class),
$excludePaths
);
}
);
}
}
2 changes: 2 additions & 0 deletions updates/version.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
1.0.0: "First version of Vdlp.Csrf -- See: https://github.com/vdlp/oc-csrf-plugin/releases/tag/1.0.0"
1.1.0: "Added configuration to exclude paths from CSRF validation -- See: https://github.com/vdlp/oc-csrf-plugin/releases/tag/1.1.0"

0 comments on commit 5aefabb

Please sign in to comment.