diff --git a/system/typemill/Middleware/CorsHeadersMiddleware.php b/system/typemill/Middleware/CorsHeadersMiddleware.php new file mode 100644 index 0000000..062db4a --- /dev/null +++ b/system/typemill/Middleware/CorsHeadersMiddleware.php @@ -0,0 +1,62 @@ +settings = $settings; + + $this->urlinfo = $urlinfo; + } + + public function process(Request $request, RequestHandler $handler) :response + { + # add the custom headers to the response after everything is processed + $response = $handler->handle($request); + + ################### + # CORS HEADER # + ################### + + $origin = $request->getHeaderLine('Origin'); + $corsdomains = isset($this->settings['corsdomains']) ? trim($this->settings['corsdomains']) : false; + $whitelist = []; + + if($corsdomains && $corsdomains != '') + { + $corsdomains = explode(",", $corsdomains); + foreach($corsdomains as $domain) + { + $domain = trim($domain); + if($domain != '') + { + $whitelist[] = $domain; + } + } + } + + if(!$origin OR $origin == '' OR !isset($whitelist[$origin])) + { + # set current website as default origin and block all cross origin calls + $origin = $this->urlinfo['baseurl']; + } + + $response = $response->withHeader('Access-Control-Allow-Origin', $origin) + ->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization') + ->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS') + ->withHeader('Access-Control-Allow-Credentials', 'true'); + + return $response; + } +} \ No newline at end of file diff --git a/system/typemill/Middleware/CspHeadersMiddleware.php b/system/typemill/Middleware/CspHeadersMiddleware.php new file mode 100644 index 0000000..9957c3e --- /dev/null +++ b/system/typemill/Middleware/CspHeadersMiddleware.php @@ -0,0 +1,67 @@ +settings = $settings; + + $this->urlinfo = $urlinfo; + } + + public function process(Request $request, RequestHandler $handler) :response + { + $scheme = $request->getUri()->getScheme(); + + # add the custom headers to the response after everything is processed + $response = $handler->handle($request); + + ################### + # CSP HEADER # + ################### + + $cspdomains = isset($this->settings['cspdomains']) ? trim($this->settings['cspdomains']) : false; + $defaultsrc = "default-src 'unsafe-inline' 'unsafe-eval' 'self'"; + + if($cspdomains && $cspdomains != '') + { + $cspdomains = explode(",", $cspdomains); + foreach($cspdomains as $cspdomain) + { + $cspdomain = trim($cspdomain); + if($cspdomain != '') + { + $defaultsrc .= ' ' . $cspdomain; + } + } + } + + # dispatch to get from plugins + # get yaml from current theme + + # Define the Content Security Policy header + $cspHeader = $defaultsrc . ";"; // Default source is restricted to 'self' +# $cspHeader .= "frame-src 'self' https://www.youtube.com;"; // Allowing embedding YouTube videos +# $cspHeader .= "img-src *"; +# $cspHeader .= "media-src *"; +# $cspHeader .= "script-src *"; +# $cspHeader .= "style-src *"; +# $cspHeader .= "object-src 'none'"; + + # Add the Content Security Policy header to the response + $response = $response->withHeader('Content-Security-Policy', $cspHeader); + + return $response; + } +} \ No newline at end of file diff --git a/system/typemill/Middleware/CustomHeadersMiddleware.php b/system/typemill/Middleware/CustomHeadersMiddleware.php index 9a19135..98a993f 100644 --- a/system/typemill/Middleware/CustomHeadersMiddleware.php +++ b/system/typemill/Middleware/CustomHeadersMiddleware.php @@ -10,14 +10,10 @@ use Slim\Psr7\Response; class CustomHeadersMiddleware implements MiddlewareInterface { protected $settings; - - protected $urlinfo; - public function __construct($settings, $urlinfo) + public function __construct($settings) { $this->settings = $settings; - - $this->urlinfo = $urlinfo; } public function process(Request $request, RequestHandler $handler) :response @@ -32,11 +28,6 @@ class CustomHeadersMiddleware implements MiddlewareInterface $headersOff = $this->settings['headersoff'] ?? false; - - ################### - # SECURITY HEADER # - ################### - if(!$headersOff) { $response = $response @@ -51,38 +42,6 @@ class CustomHeadersMiddleware implements MiddlewareInterface } } - ################### - # CORS HEADER # - ################### - - $origin = $request->getHeaderLine('Origin'); - $corsdomains = isset($this->settings['corsdomains']) ? trim($this->settings['corsdomains']) : false; - $whitelist = []; - - if($corsdomains && $corsdomains != '') - { - $corsdomains = explode(",", $corsdomains); - foreach($corsdomains as $domain) - { - $domain = trim($domain); - if($domain != '') - { - $whitelist[] = $domain; - } - } - } - - if(!$origin OR $origin == '' OR !isset($whitelist[$origin])) - { - # set current website as default origin and block all cross origin calls - $origin = $this->urlinfo['baseurl']; - } - - $response = $response->withHeader('Access-Control-Allow-Origin', $origin) - ->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization') - ->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS') - ->withHeader('Access-Control-Allow-Credentials', 'true'); - return $response; } } \ No newline at end of file diff --git a/system/typemill/routes/api.php b/system/typemill/routes/api.php index 05bd1bb..da573f3 100644 --- a/system/typemill/routes/api.php +++ b/system/typemill/routes/api.php @@ -3,6 +3,7 @@ use Slim\Routing\RouteCollectorProxy; use Typemill\Middleware\ApiAuthentication; use Typemill\Middleware\ApiAuthorization; +use Typemill\Middleware\CorsHeadersMiddleware; use Typemill\Controllers\ControllerApiGlobals; use Typemill\Controllers\ControllerApiMedia; use Typemill\Controllers\ControllerApiSystemSettings; @@ -85,7 +86,7 @@ $app->group('/api/v1', function (RouteCollectorProxy $group) use ($acl) { $group->get('/meta', ControllerApiAuthorMeta::class . ':getMeta')->setName('api.meta.get')->add(new ApiAuthorization($acl, 'mycontent', 'view')); $group->post('/meta', ControllerApiAuthorMeta::class . ':updateMeta')->setName('api.metadata.update')->add(new ApiAuthorization($acl, 'mycontent', 'update')); -})->add(new ApiAuthentication()); +})->add(new CorsHeadersMiddleware($settings, $urlinfo))->add(new ApiAuthentication()); # api-routes from plugins if(isset($routes['api']) && !empty($routes['api'])) @@ -102,12 +103,12 @@ if(isset($routes['api']) && !empty($routes['api'])) if($resources && $privilege) { # protected api requires authentication and authorization - $app->{$method}($route, $class)->setName($name)->add(new ApiAuthorization($acl, $resource, $privilege))->add(new ApiAuthentication()); + $app->{$method}($route, $class)->setName($name)->add(new ApiAuthorization($acl, $resource, $privilege))->add(new CorsHeadersMiddleware($settings, $urlinfo))->add(new ApiAuthentication()); } else { # public api routes - $app->{$method}($route, $class)->setName($name); + $app->{$method}($route, $class)->setName($name)->add(new CorsHeadersMiddleware($settings, $urlinfo)); } } } \ No newline at end of file diff --git a/system/typemill/system.php b/system/typemill/system.php index 3319999..4602df9 100644 --- a/system/typemill/system.php +++ b/system/typemill/system.php @@ -323,7 +323,7 @@ foreach($middleware as $pluginMiddleware) } } -$app->add(new CustomHeadersMiddleware($settings, $urlinfo)); +$app->add(new CustomHeadersMiddleware($settings)); $app->add(new AssetMiddleware($assets, $container->get('view')));