Skip to content

Commit

Permalink
Default storage restored to $_SESSION
Browse files Browse the repository at this point in the history
  • Loading branch information
Slamdunk committed Dec 20, 2016
1 parent 9aa3d20 commit f43cb59
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 11 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,26 @@ $app->post('/api/myEndPoint',function ($request, $response, $args) {
$app->run();
```

### Manual usage

If you are willing to use `Slim\Csrf\Guard` outside a `Slim\App` or not as a middleware, be careful to validate the storage:

```php
// Start PHP session
session_start();

$slimGuard = new \Slim\Csrf\Guard;
$slimGuard->validateStorage();

// Generate new tokens
$csrfNameKey = $slimGuard->getTokenNameKey();
$csrfValueKey = $slimGuard->getTokenValueKey();
$keyPair = $slimGuard->generateToken();

// Validate retrieved tokens
$slimGuard->validateToken($_POST[$csrfNameKey], $_POST[$csrfValueKey]);
```

## Token persistence

By default, `Slim\Csrf\Guard` will generate a fresh name/value pair after each request. This is an important security measure for [certain situations](http://blog.ircmaxell.com/2013/02/preventing-csrf-attacks.html). However, in many cases this is unnecessary, and [a single token throughout the user's session will suffice](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#Synchronizer_.28CSRF.29_Tokens). By using per-session requests it becomes easier, for example, to process AJAX requests without having to retrieve a new CSRF token (by reloading the page or making a separate request) after each request. See issue #49.
Expand Down
24 changes: 13 additions & 11 deletions src/Guard.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,22 +172,24 @@ public function __invoke(ServerRequestInterface $request, ResponseInterface $res
* @param $storage
* @return mixed
*/
private function validateStorage()
public function validateStorage()
{
if (is_array($this->storage)) {
return $this->storage;
} elseif ($this->storage instanceof ArrayAccess) {
return $this->storage;
} else {
if (!isset($_SESSION)) {
throw new RuntimeException('CSRF middleware failed. Session not found.');
}
if (!array_key_exists($this->prefix, $_SESSION)) {
$_SESSION[$this->prefix] = [];
}
$this->storage = &$_SESSION[$this->prefix];
}

if ($this->storage instanceof ArrayAccess) {
return $this->storage;
}

if (!isset($_SESSION)) {
throw new RuntimeException('CSRF middleware failed. Session not found.');
}
if (!array_key_exists($this->prefix, $_SESSION)) {
$_SESSION[$this->prefix] = [];
}
$this->storage = &$_SESSION[$this->prefix];
return $this->storage;
}

/**
Expand Down
13 changes: 13 additions & 0 deletions tests/CsrfTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -393,4 +393,17 @@ public function testKeyPair() {

$this->assertNotNull($mw->getTokenValue());
}

public function testDefaultStorageIsSession()
{
$sessionBackup = $_SESSION;
$_SESSION = array();

$mw = new Guard('csrf');
$mw->validateStorage();

$this->assertNotEmpty($_SESSION);

$_SESSION = $sessionBackup;
}
}

0 comments on commit f43cb59

Please sign in to comment.