Index: typo3/index.php
===================================================================
--- typo3/index.php (revision 10518)
+++ typo3/index.php (working copy)
@@ -398,7 +398,8 @@
t3lib_utility_Http::redirect($this->redirectToURL);
} else {
$formprotection = t3lib_formprotection_Factory::get();
- $token = $formprotection->generateToken('extDirect');
+ $accessToken = $formprotection->generateToken('refreshTokens');
+ $formprotection->persistTokens();
$TBE_TEMPLATE->JScode.=$TBE_TEMPLATE->wrapScriptTags('
if (parent.opener && (parent.opener.busy || parent.opener.TYPO3.loginRefresh)) {
if (parent.opener.TYPO3.loginRefresh) {
@@ -406,7 +407,7 @@
} else {
parent.opener.busy.loginRefreshed();
}
- parent.opener.TYPO3.ExtDirectToken = "' . $token . '";
+ parent.opener.TYPO3.loginRefresh.refreshTokens("' . $accessToken . '");
parent.close();
}
');
Index: typo3/js/extjs/viewportConfiguration.js
===================================================================
--- typo3/js/extjs/viewportConfiguration.js (revision 10518)
+++ typo3/js/extjs/viewportConfiguration.js (working copy)
@@ -89,7 +89,8 @@
id: 'typo3-navigationIframe',
border: false,
hidden: true,
- xtype: 'iframePanel'
+ xtype: 'iframePanel',
+ name: 'navigation'
}
]
},
Index: typo3/js/loginrefresh.js
===================================================================
--- typo3/js/loginrefresh.js (revision 10518)
+++ typo3/js/loginrefresh.js (working copy)
@@ -226,7 +226,7 @@
control.updateText(String.format(TYPO3.LLL.core.refresh_login_countdown, rest));
}
});
-
+
this.loginRefreshWindow.on('close', function(){
TYPO3.loginRefresh.startTimer();
});
@@ -306,7 +306,7 @@
// User is logged in
Ext.getCmp("loginformWindow").hide();
TYPO3.loginRefresh.startTimer();
- TYPO3.ExtDirectToken = result.token;
+ TYPO3.loginRefresh.refreshTokens(result.accessToken);
} else {
// TODO: add failure to notification system instead of alert
Ext.Msg.alert(TYPO3.LLL.core.refresh_login_failed, TYPO3.LLL.core.refresh_login_failed_message);
@@ -337,6 +337,97 @@
} else {
this.submitForm();
}
+ },
+
+ getOutdatedTokens: function() {
+ var tokens = [];
+ var searchTokenPlaces = [top, top.content.document];
+
+ if (top.nav instanceof TYPO3.iframePanel) {
+ searchTokenPlaces.push(top.nav.getIframe());
+ }
+
+ Ext.each(searchTokenPlaces, function(searchPlace) {
+ var links = searchPlace.Ext.query('a[href*=formToken]');
+ Ext.each(links, function(linkTag) {
+ tokens.push(Ext.urlDecode(linkTag.href).formToken);
+ });
+
+ var formFields = searchPlace.Ext.query("form input[name=formToken]");
+ Ext.each(formFields, function(inputField) {
+ tokens.push(inputField.value);
+ });
+
+ var linksOnclick = searchPlace.Ext.query('a[onclick*=formToken]');
+ Ext.each(linksOnclick, function(linkTag) {
+ tokens.push(linkTag.attributes.onclick.value.match(/&formToken=([^&]*)&/).pop());
+ });
+
+ if (Ext.isString(searchPlace.TYPO3.ExtDirectToken)) {
+ tokens.push(searchPlace.TYPO3.ExtDirectToken);
+ }
+
+ });
+
+ return tokens;
+ },
+
+ replaceOutdatedTokens: function(newTokens) {
+ var searchTokenPlaces = [top, top.content.document];
+
+ if (top.nav instanceof TYPO3.iframePanel) {
+ searchTokenPlaces.push(top.nav.getIframe());
+ }
+
+ Ext.each(searchTokenPlaces, function(searchPlace) {
+ var links = searchPlace.Ext.query('a[href*=formToken]');
+ Ext.each(links, function(linkTag) {
+ var url = Ext.urlDecode(linkTag.href);
+ url.formToken = newTokens[url.formToken];
+ linkTag.href = unescape(Ext.urlEncode(url));
+ });
+
+ var formFields = searchPlace.Ext.query("form input[name=formToken]");
+ Ext.each(formFields, function(inputField) {
+ inputField.value = newTokens[inputField.value];
+ });
+
+ var linksOnclick = searchPlace.Ext.query('a[onclick*=formToken]');
+ Ext.each(linksOnclick, function(linkTag) {
+ var token = linkTag.attributes.onclick.value.match(/&formToken=([^&]*)&/).pop();
+ linkTag.attributes.onclick.value = linkTag.attributes.onclick.value.replace(new RegExp(token), newTokens[token]);
+ });
+
+ if (Ext.isString(searchPlace.TYPO3.ExtDirectToken)) {
+ searchPlace.TYPO3.ExtDirectToken = newTokens[searchPlace.TYPO3.ExtDirectToken];
+ }
+ });
+ },
+
+ refreshTokens: function(accessToken) {
+ Ext.Ajax.request({
+ url: "ajax.php",
+ params: {
+ "ajaxID": "BackendLogin::refreshTokens",
+ "accessToken": accessToken,
+ "tokens": Ext.encode(this.getOutdatedTokens())
+ },
+ method: "POST",
+ scope: this,
+ success: function(response, opts) {
+ var result = Ext.util.JSON.decode(response.responseText);
+ TYPO3.loginRefresh.replaceOutdatedTokens(result.newTokens);
+ },
+ failure: function(response, opts) {
+ TYPO3.Flashmessage.display(
+ TYPO3.Severity.error,
+ 'Refresh tokens',
+ 'Refreshing tokens after relogin faild. Please reload the backend.',
+ 30
+ );
+ }
+
+ });
}
});
Index: typo3/classes/class.ajaxlogin.php
===================================================================
--- typo3/classes/class.ajaxlogin.php (revision 10518)
+++ typo3/classes/class.ajaxlogin.php (working copy)
@@ -43,14 +43,14 @@
* @return void
*/
public function login(array $parameters, TYPO3AJAX $ajaxObj) {
- if ($GLOBALS['BE_USER']->user['uid']) {
- $formprotection = t3lib_formprotection_Factory::get();
- $token = $formprotection->generateToken('extDirect');
-
- $json = array(
- 'success' => TRUE,
- 'token' => $token
- );
+ if ($this->isAuthorizedBackendSession()) {
+ $json = array('success' => TRUE);
+ $token = '';
+ if ($this->hasLoginBeenProcessed()) {
+ $formprotection = t3lib_formprotection_Factory::get();
+ $json['accessToken'] = $formprotection->generateToken('refreshTokens');
+ $formprotection->persistTokens();
+ }
} else {
$json = array('success' => FALSE);
}
@@ -59,6 +59,30 @@
}
/**
+ * Checks if a user is logged in and the session is active.
+ *
+ * @return boolean
+ */
+ protected function isAuthorizedBackendSession() {
+ return (isset($GLOBALS['BE_USER']) && $GLOBALS['BE_USER'] instanceof t3lib_beUserAuth && isset($GLOBALS['BE_USER']->user['uid']));
+ }
+
+ /**
+ * Check whether the user was not already authorized
+ *
+ * @return boolean
+ */
+ protected function hasLoginBeenProcessed() {
+ $loginFormData = $GLOBALS['BE_USER']->getLoginFormData();
+
+ return ($loginFormData['status'] == 'login')
+ && isset($loginFormData['uname'])
+ && isset($loginFormData['uident'])
+ && isset($loginFormData['chalvalue'])
+ && ((string)$_COOKIE['be_typo_user'] !== (string)$GLOBALS['BE_USER']->id);
+ }
+
+ /**
* Logs out the current BE user
*
* @param array $parameters: Parameters (not used)
@@ -140,6 +164,43 @@
$parent->addContent('challenge', $_SESSION['login_challenge']);
$parent->setContentFormat('json');
}
+
+ /**
+ * Generates new tokens for the ones found in the DOM.
+ *
+ * @param array $parameters: Parameters (not used)
+ * @param TYPO3AJAX $parent: The calling parent AJAX object
+ */
+ public function refreshTokens(array $parameters, TYPO3AJAX $parent) {
+ $accessToken = (string)t3lib_div::_GP('accessToken');
+ $formprotection = t3lib_formprotection_Factory::get();
+
+ if ($formprotection->validateToken($accessToken, 'refreshTokens')) {
+ $oldTokens = json_decode((string)t3lib_div::_GP('tokens'));
+ $regeneratedTokens = new stdClass();
+
+ foreach ($oldTokens as $oldToken) {
+ $newToken = $this->generateNewToken($oldToken);
+ $regeneratedTokens->$oldToken = $newToken;
+ }
+ }
+ $parent->addContent('newTokens', $regeneratedTokens);
+ $parent->setContentFormat('json');
+
+ $formprotection->persistTokens();
+ }
+
+ /**
+ * Generate new token.
+ *
+ * @param string $oldToken
+ * @return string regenerated Token
+ */
+ protected function generateNewToken($oldToken) {
+ list ($tokenId, $formName) = explode('-', $oldToken);
+ return t3lib_formprotection_Factory::get()->generateToken($formName) . '-' . $formName;
+ }
+
}
if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['typo3/classes/class.ajaxlogin.php'])) {
Index: t3lib/class.t3lib_pagerenderer.php
===================================================================
--- t3lib/class.t3lib_pagerenderer.php (revision 10518)
+++ t3lib/class.t3lib_pagerenderer.php (working copy)
@@ -986,7 +986,7 @@
// does this only with multiple arguments
$this->addExtOnReadyCode('
(function() {
- TYPO3.ExtDirectToken = "' . $token . '";
+ TYPO3.ExtDirectToken = "' . $token . '-extDirect";
for (var api in Ext.app.ExtDirectAPI) {
var provider = Ext.Direct.addProvider(Ext.app.ExtDirectAPI[api]);
provider.on("beforecall", function(provider, transaction, meta) {
Index: t3lib/config_default.php
===================================================================
--- t3lib/config_default.php (revision 10518)
+++ t3lib/config_default.php (working copy)
@@ -510,6 +510,7 @@
'BackendLogin::refreshLogin' => 'typo3/classes/class.ajaxlogin.php:AjaxLogin->refreshLogin',
'BackendLogin::isTimedOut' => 'typo3/classes/class.ajaxlogin.php:AjaxLogin->isTimedOut',
'BackendLogin::getChallenge' => 'typo3/classes/class.ajaxlogin.php:AjaxLogin->getChallenge',
+ 'BackendLogin::refreshTokens' => 'typo3/classes/class.ajaxlogin.php:AjaxLogin->refreshTokens',
'DonateWindow::disable' => 'typo3/classes/class.donatewindow.php:DonateWindow->disable',
'DonateWindow::postpone' => 'typo3/classes/class.donatewindow.php:DonateWindow->postpone',
'ExtDirect::getAPI' => 't3lib/extjs/class.t3lib_extjs_extdirectapi.php:t3lib_extjs_ExtDirectApi->getAPI',
Index: t3lib/class.t3lib_tceforms.php
===================================================================
--- t3lib/class.t3lib_tceforms.php (revision 10518)
+++ t3lib/class.t3lib_tceforms.php (working copy)
@@ -4983,7 +4983,7 @@
*/
public static function getHiddenTokenField($formName = 'securityToken', $tokenName = 'formToken') {
$formprotection = t3lib_formprotection_Factory::get();
- return '';
+ return '';
}
/**
Index: t3lib/class.t3lib_befunc.php
===================================================================
--- t3lib/class.t3lib_befunc.php (revision 10518)
+++ t3lib/class.t3lib_befunc.php (working copy)
@@ -3333,7 +3333,7 @@
*/
public static function getUrlToken($formName = 'securityToken', $tokenName = 'formToken') {
$formprotection = t3lib_formprotection_Factory::get();
- return '&' . $tokenName . '=' . $formprotection->generateToken($formName);
+ return '&' . $tokenName . '=' . $formprotection->generateToken($formName) . '-' . $formName;
}
/*******************************************
Index: t3lib/formprotection/class.t3lib_formprotection_backendformprotection.php
===================================================================
--- t3lib/formprotection/class.t3lib_formprotection_backendformprotection.php (revision 10518)
+++ t3lib/formprotection/class.t3lib_formprotection_backendformprotection.php (working copy)
@@ -152,6 +152,20 @@
}
/**
+ * Override the abstract class to be able to strip out
+ * the token id from the POST variable.
+ *
+ * @see t3lib/formprotection/t3lib_formprotection_Abstract::validateToken()
+ */
+ public function validateToken(
+ $token, $formName, $action = '', $formInstanceName = ''
+ ) {
+ list($tokenId, $_) = explode('-', (string)$token);
+
+ return parent::validateToken($tokenId, $formName, $action, $formInstanceName);
+ }
+
+ /**
* Creates or displayes an error message telling the user that the submitted
* form token is invalid.
*