Elgg  Version 5.1
Csrf.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Elgg\Security;
4 
5 use Elgg\Config;
7 use Elgg\Request;
9 
13 class Csrf {
14 
15  use TimeUsing;
16 
20  protected $config;
21 
25  protected $session;
26 
30  protected $crypto;
31 
35  protected $hmac;
36 
45  public function __construct(
50  ) {
51 
52  $this->config = $config;
53  $this->session = $session;
54  $this->crypto = $crypto;
55  $this->hmac = $hmac;
56  }
57 
66  public function validate(Request $request) {
67  $token = $request->getParam('__elgg_token');
68  $ts = $request->getParam('__elgg_ts');
69 
70  $session_id = $this->session->getID();
71 
72  if (($token) && ($ts) && ($session_id)) {
73  if ($this->validateTokenOwnership($token, $ts)) {
74  if ($this->validateTokenTimestamp($ts)) {
75  // We have already got this far, so unless anything
76  // else says something to the contrary we assume we're ok
77  $returnval = $request->elgg()->events->triggerResults('action_gatekeeper:permissions:check', 'all', [
78  'token' => $token,
79  'time' => $ts
80  ], true);
81 
82  if ($returnval) {
83  return;
84  } else {
85  throw new CsrfException($request->elgg()->translator->translate('actiongatekeeper:pluginprevents'));
86  }
87  } else {
88  // this is necessary because of #5133
89  if ($request->isXhr()) {
90  throw new CsrfException($request->elgg()->translator->translate(
91  'js:security:token_refresh_failed',
92  [$this->config->wwwroot]
93  ));
94  } else {
95  throw new CsrfException($request->elgg()->translator->translate('actiongatekeeper:timeerror'));
96  }
97  }
98  } else {
99  // this is necessary because of #5133
100  if ($request->isXhr()) {
101  throw new CsrfException($request->elgg()->translator->translate('js:security:token_refresh_failed', [$this->config->wwwroot]));
102  } else {
103  throw new CsrfException($request->elgg()->translator->translate('actiongatekeeper:tokeninvalid'));
104  }
105  }
106  } else {
107  $error_msg = $request->elgg()->translator->translate('actiongatekeeper:missingfields');
108  throw new CsrfException($error_msg);
109  }
110  }
111 
122  public function isValidToken($token, $ts) {
123  return $this->validateTokenOwnership($token, $ts) && $this->validateTokenTimestamp($ts);
124  }
125 
133  protected function validateTokenTimestamp($ts) {
134  $timeout = $this->getActionTokenTimeout();
135  $now = $this->getCurrentTime()->getTimestamp();
136 
137  return ($timeout == 0 || ($ts > $now - $timeout) && ($ts < $now + $timeout));
138  }
139 
149  public function getActionTokenTimeout() {
150  // default to 2 hours
151  $timeout = 2;
152  if ($this->config->hasValue('action_token_timeout')) {
153  // timeout set in config
154  $timeout = $this->config->action_token_timeout;
155  }
156 
157  $hour = 60 * 60;
158 
159  return (int) ((float) $timeout * $hour);
160  }
161 
172  public function validateTokenOwnership($token, $timestamp, $session_token = '') {
173  $required_token = $this->generateActionToken($timestamp, $session_token);
174 
175  return $this->crypto->areEqual($token, $required_token);
176  }
177 
187  public function generateActionToken($timestamp, $session_token = '') {
188  if (!$session_token) {
189  $session_token = $this->session->get('__elgg_session');
190  if (!$session_token) {
191  return false;
192  }
193  }
194 
195  return $this->hmac
196  ->getHmac([(int) $timestamp, $session_token], 'md5')
197  ->getToken();
198  }
199 }
isValidToken($token, $ts)
Basic token validation.
Definition: Csrf.php:122
getActionTokenTimeout()
Returns the action token timeout in seconds.
Definition: Csrf.php:149
Cryptographic services.
Definition: Crypto.php:12
$request
Definition: livesearch.php:12
trait TimeUsing
Adds methods for setting the current time (for testing)
Definition: TimeUsing.php:10
$timestamp
Definition: date.php:34
getParam($key, $default=null, $filter=true)
Get an element of the params array.
Definition: Request.php:79
isXhr()
Is the route access with XmlHttpRequest.
Definition: Request.php:161
Elgg Session Management.
Definition: ElggSession.php:19
getCurrentTime($modifier= '')
Get the (cloned) time.
Definition: TimeUsing.php:25
__construct(Config $config,\ElggSession $session, Crypto $crypto, HmacFactory $hmac)
Constructor.
Definition: Csrf.php:45
validateTokenTimestamp($ts)
Is the token timestamp within acceptable range?
Definition: Csrf.php:133
validateTokenOwnership($token, $timestamp, $session_token= '')
Was the given token generated for the session defined by session_token?
Definition: Csrf.php:172
Thrown when CSRF tokens mismatch.
elgg()
Get the DI container.
Definition: Request.php:137
$token
validate(Request $request)
Validate CSRF tokens present in the request.
Definition: Csrf.php:66
$ts
CSRF security token view for use with secure forms.
Request container.
Definition: Request.php:12
CSRF Protection.
Definition: Csrf.php:13
generateActionToken($timestamp, $session_token= '')
Generate a token from a session token (specifying the user), the timestamp, and the site key...
Definition: Csrf.php:187
Provides a factory for HMAC objects.
Definition: HmacFactory.php:10