Skip to content
This repository has been archived by the owner on Jan 8, 2025. It is now read-only.

Commit

Permalink
Merge pull request #99 from serato/WEB-7503
Browse files Browse the repository at this point in the history
[WEB-7503]: add FrameAncestorsCspHeader
  • Loading branch information
aosmakserato authored Mar 28, 2023
2 parents 2deff86 + 6e958f0 commit 0aa3b7b
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 0 deletions.
36 changes: 36 additions & 0 deletions src/Slim/Middleware/FrameAncestorsCspHeader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Serato\SwsApp\Slim\Middleware;

use Psr\Http\Message\RequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
use Slim\Handlers\AbstractHandler;

/**
* Class FrameAncestorsCspHeader
*
* Adds a CSP header with frame-ancestors rule, which gets merged with the other CSP rules by a browser.
* Applications where this middleware is used, can't be framed inside a frame or iframe tag.
*
* @package App\Middleware
*/
class FrameAncestorsCspHeader extends AbstractHandler
{
/**
* Invoke the middleware
*
* @param Request $request The most recent Request object
* @param Response $response The most recent Response object
* @param Callable $next The next middleware to call
*
* @return Response
*/
public function __invoke(Request $request, Response $response, callable $next): Response
{
$response = $next($request, $response);
$response = $response
->withAddedHeader('Content-Security-Policy', "frame-ancestors 'none';");

return $response;
}
}
72 changes: 72 additions & 0 deletions tests/Slim/Middleware/FrameAncestorsCspHeaderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

namespace Serato\SwsApp\Test\Slim\Middleware;

use Serato\SwsApp\Test\TestCase;
use Serato\SwsApp\Slim\Middleware\EmptyWare;
use Serato\Slimulator\EnvironmentBuilder;
use Serato\Slimulator\Request;
use Slim\Http\Response;
use Serato\SwsApp\Slim\Middleware\FrameAncestorsCspHeader;

/**
* Class FrameAncestorsCspHeaderTest
* @package Serato\SwsApp\Test\Slim\Middleware
*/
class FrameAncestorsCspHeaderTest extends TestCase
{
private const CSP_VALUE = "frame-ancestors 'none'";

/**
* Create an Request object and Response object.
*
* Execute the middleware and get the returned Response object.
*
* Confirm that the Response object has:
*
* - A `Content-Security-Policy` header whose value is always "frame-ancestors 'none';".
*/
public function testWithOriginRequestHeader()
{
$middleware = new FrameAncestorsCspHeader();

$response = $middleware(
Request::createFromEnvironmentBuilder(EnvironmentBuilder::create()),
new Response(),
new EmptyWare()
);

$this->assertNotFalse(
strpos($response->getHeaderLine('Content-Security-Policy'), self::CSP_VALUE)
);
}

/**
* Create a Request object.
* Create a Response object with a `Content-Security-Policy` header that contains an initial value.
*
* Execute the middleware and get the returned Response object.
*
* Confirm that the Response object has:
*
* - A `Content-Security-Policy` header whose value contains both the initial value and "frame-ancestors 'none'".
*/
public function testWithOriginRequestHeaderAndExistingCspResponseHeader()
{
$initialValue = "default-src 'none';";

$middleware = new FrameAncestorsCspHeader();

$response = new Response();
$response = $middleware(
Request::createFromEnvironmentBuilder(EnvironmentBuilder::create()),
$response->withHeader('Content-Security-Policy', $initialValue),
new EmptyWare()
);

$this->assertNotFalse(strpos($response->getHeaderLine('Content-Security-Policy'), $initialValue));
$this->assertNotFalse(
strpos($response->getHeaderLine('Content-Security-Policy'), self::CSP_VALUE)
);
}
}

0 comments on commit 0aa3b7b

Please sign in to comment.