Skip to content

Commit

Permalink
Merge pull request #422 from creative-commoners/pulls/4.2/disable-cac…
Browse files Browse the repository at this point in the history
…he-on-endpoints

FIX Disable HTTP caching on all relevant MFA API endpoints
  • Loading branch information
emteknetnz authored Feb 3, 2021
2 parents acfb0f3 + b1f48d5 commit 296c7ed
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 18 deletions.
11 changes: 11 additions & 0 deletions src/Authenticator/LoginHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Psr\Log\LoggerInterface;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\Middleware\HTTPCacheControlMiddleware;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\MFA\Exception\InvalidMethodException;
use SilverStripe\MFA\Exception\MemberNotFoundException;
Expand Down Expand Up @@ -159,9 +160,13 @@ public function mfa(HTTPRequest $request)
*/
public function getSchema(): HTTPResponse
{
// Prevent caching of response
HTTPCacheControlMiddleware::singleton()->disableCache(true);

try {
$member = $this->getMember();
$schema = SchemaGenerator::create()->getSchema($member);

return $this->jsonResponse(
$schema + [
'endpoints' => [
Expand All @@ -186,6 +191,9 @@ public function getSchema(): HTTPResponse
*/
public function startRegistration(HTTPRequest $request): HTTPResponse
{
// Prevent caching of response
HTTPCacheControlMiddleware::singleton()->disableCache(true);

$store = $this->getStore();
$sessionMember = $store ? $store->getMember() : null;
$loggedInMember = Security::getCurrentUser();
Expand Down Expand Up @@ -344,6 +352,9 @@ public function skipRegistration(HTTPRequest $request): HTTPResponse
*/
public function startVerification(HTTPRequest $request): HTTPResponse
{
// Prevent caching of response
HTTPCacheControlMiddleware::singleton()->disableCache(true);

$store = $this->getStore();
// If we don't have a valid member we shouldn't be here, or if sudo mode is not active yet.
if (!$store || !$store->getMember() || !$this->getSudoModeService()->check($request->getSession())) {
Expand Down
4 changes: 4 additions & 0 deletions src/Controller/AdminRegistrationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use SilverStripe\Admin\LeftAndMain;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\Middleware\HTTPCacheControlMiddleware;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\MFA\Extension\MemberExtension;
use SilverStripe\MFA\RequestHandler\BaseHandlerTrait;
Expand Down Expand Up @@ -66,6 +67,9 @@ class AdminRegistrationController extends LeftAndMain
*/
public function startRegistration(HTTPRequest $request): HTTPResponse
{
// Prevent caching of response
HTTPCacheControlMiddleware::singleton()->disableCache(true);

// Create a fresh store from the current logged in user
$member = Security::getCurrentUser();
$store = $this->createStore($member);
Expand Down
4 changes: 0 additions & 4 deletions src/RequestHandler/VerificationHandlerTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\Middleware\HTTPCacheControlMiddleware;
use SilverStripe\Core\Config\Config;
use SilverStripe\MFA\Exception\InvalidMethodException;
use SilverStripe\MFA\Method\MethodInterface;
Expand Down Expand Up @@ -76,9 +75,6 @@ protected function createStartVerificationResponse(
$token->reset();
$data[$token->getName()] = $token->getValue();

// Prevent caching of response
HTTPCacheControlMiddleware::singleton()->disableCache(true);

// Respond with our method
return $response->setBody(json_encode($data));
}
Expand Down
46 changes: 32 additions & 14 deletions tests/php/Authenticator/LoginHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -335,24 +335,42 @@ public function testStartVerificationIncludesACSRFToken()
$this->assertTrue(SecurityToken::inst()->check($response->SecurityID));
}

// This is testing that HTTP caching headers that disable caching are set
// in VerificationHandlerTrait::createStartVerificationResponse()
// VerificationHandlerTrait is used by LoginHandler
public function testStartVerificationHttpCacheHeadersDisabled()
/**
* Test that HTTP caching is disabled in requests to the schema endpoint
*/
public function testSchemaDisablesHTTPCaching()
{
$middleware = HTTPCacheControlMiddleware::singleton();
$middleware->enableCache(true);
$this->assertSame('enabled', $middleware->getState());

$this->get(Controller::join_links(Security::login_url(), 'default/mfa/schema'));
$this->assertSame('disabled', $middleware->getState());
}

/**
* Test that HTTP caching is disabled in requests to the registration endpoint
*/
public function testStartRegistrationDisablesHTTPCaching()
{
$middleware = HTTPCacheControlMiddleware::singleton();
$middleware->enableCache(true);
$this->assertSame('enabled', $middleware->getState());

$this->get(Controller::join_links(Security::login_url(), 'default/mfa/register/basic-math'));
$this->assertSame('disabled', $middleware->getState());
}

/**
* Test that HTTP caching is disabled in requests to the verification endpoint
*/
public function testStartVerificationDisablesHTTPCaching()
{
/** @var Member $member */
SecurityToken::enable();
$handler = new LoginHandler('mfa', $this->createMock(MemberAuthenticator::class));
$member = $this->objFromFixture(Member::class, 'robbie');
$store = new SessionStore($member);
$handler->setStore($store);
$request = new HTTPRequest('GET', '/');
$request->setSession(new Session([]));
$request->setRouteParams(['Method' => 'basic-math']);
$middleware = HTTPCacheControlMiddleware::singleton();
$middleware->enableCache(true);
$this->assertSame('enabled', $middleware->getState());
$handler->startVerification($request);

$this->get(Controller::join_links(Security::login_url(), 'default/mfa/verify/basic-math'));
$this->assertSame('disabled', $middleware->getState());
}

Expand Down
14 changes: 14 additions & 0 deletions tests/php/Controller/AdminRegistrationControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use SilverStripe\Admin\AdminRootController;
use SilverStripe\Control\Controller;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\Middleware\HTTPCacheControlMiddleware;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\FunctionalTest;
Expand Down Expand Up @@ -84,6 +85,19 @@ public function testStartRegistrationReturns200Response()
$this->assertSame(200, $result->getStatusCode());
}

/**
* Test that HTTP caching is disabled in requests to the registration endpoint
*/
public function testStartRegistrationDisablesHTTPCaching()
{
$middleware = HTTPCacheControlMiddleware::singleton();
$middleware->enableCache(true);
$this->assertSame('enabled', $middleware->getState());

$this->get(Controller::join_links(AdminRootController::admin_url(), 'mfa', 'register/foo'));
$this->assertSame('disabled', $middleware->getState());
}

public function testFinishRegistrationGracefullyHandlesInvalidSessions()
{
$this->logInAs($this->objFromFixture(Member::class, 'sally_smith'));
Expand Down

0 comments on commit 296c7ed

Please sign in to comment.