1
0
mirror of https://github.com/flarum/core.git synced 2025-10-10 22:44:25 +02:00

Overhaul sessions, tokens, and authentication

- Use cookies + CSRF token for API authentication in the default client. This mitigates potential XSS attacks by making the token unavailable to JavaScript. The Authorization header is still supported, but not used by default.
- Make sensitive/destructive actions (editing a user, permanently deleting anything, visiting the admin CP) require the user to re-enter their password if they haven't entered it in the last 30 minutes.
- Refactor and clean up the authentication middleware.
- Add an `onhide` hook to the Modal component. (+1 squashed commit)
This commit is contained in:
Toby Zerner
2015-11-05 16:17:00 +10:30
parent a1e1635019
commit 9896378b59
69 changed files with 1076 additions and 509 deletions

View File

@@ -10,82 +10,43 @@
namespace Flarum\Http\Middleware;
use Flarum\Api\AccessToken;
use Flarum\Core\Guest;
use Flarum\Locale\LocaleManager;
use Flarum\Http\Exception\TokenMismatchException;
use Flarum\Http\Session;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Zend\Stratigility\MiddlewareInterface;
class AuthenticateWithCookie implements MiddlewareInterface
{
/**
* @var LocaleManager
*/
protected $locales;
/**
* @param LocaleManager $locales
*/
public function __construct(LocaleManager $locales)
{
$this->locales = $locales;
}
/**
* {@inheritdoc}
*/
public function __invoke(Request $request, Response $response, callable $out = null)
{
$request = $this->logIn($request);
$id = array_get($request->getCookieParams(), 'flarum_session');
if ($id) {
$session = Session::find($id);
$request = $request->withAttribute('session', $session);
if (! $this->isReading($request) && ! $this->tokensMatch($request)) {
throw new TokenMismatchException;
}
}
return $out ? $out($request, $response) : $response;
}
/**
* Set the application's actor instance according to the request token.
*
* @param Request $request
* @return Request
*/
protected function logIn(Request $request)
private function isReading(Request $request)
{
$actor = new Guest;
if ($token = $this->getToken($request)) {
if (! $token->isValid()) {
// TODO: https://github.com/flarum/core/issues/253
} elseif ($token->user) {
$actor = $token->user;
$actor->updateLastSeen()->save();
}
}
if ($actor->exists) {
$locale = $actor->getPreference('locale');
} else {
$locale = array_get($request->getCookieParams(), 'locale');
}
if ($locale && $this->locales->hasLocale($locale)) {
$this->locales->setLocale($locale);
}
return $request->withAttribute('actor', $actor);
return in_array($request->getMethod(), ['HEAD', 'GET', 'OPTIONS']);
}
/**
* Get the access token referred to by the request cookie.
*
* @param Request $request
* @return AccessToken|null
*/
protected function getToken(Request $request)
private function tokensMatch(Request $request)
{
$token = array_get($request->getCookieParams(), 'flarum_remember');
$input = $request->getHeaderLine('X-CSRF-Token') ?: array_get($request->getParsedBody(), 'token');
if ($token) {
return AccessToken::find($token);
}
return $request->getAttribute('session')->csrf_token === $input;
}
}