In TYPO3 10 is there a way to disable a page for anyone not logged in to the backend. Prior to Typo3 10, I believe something like this worked:
[getTSFE() && getTSFE().isBackendUserLoggedIn() == false]
page = PAGE
page.10 = TEXT
page.10.value = Page disabled
[GLOBAL]
But in Typo3 10 this does not work any more because of changes in the TSFE Array.
Since 9.5.16/10.4.1, you could use [backend.user.isLoggedIn] or [backend.user.isAdmin] (TSref) for checking BE user properties.
Maybe it would be a better approach to "hide" the page for unwanted visitors by setting an HTTP auth...
Update:
Tested both variants. Both condition variants are matching in an TYPO3 v10.4.17/10.4.19:
page.200 = TEXT
[getTSFE() && getTSFE().isBackendUserLoggedIn() == true]
page.200.value = BE-User is logged in.
[getTSFE() && getTSFE().isBackendUserLoggedIn() == false]
page.200.value = BE-User is NOT logged in.
[global]
page.250 = TEXT
page.250.value = <hr />
page.300 = TEXT
page.300.value = BE-User is NOT logged in.
[backend.user.isLoggedIn]
page.300.value = BE-User is logged in.
[global]
Notice:
To get this work, your FE and BE must be able to share their session cookie. This means, both must be called with same domain (or appropriately configured cookie domain). Be aware with multi-domain instance and the variants with/without "www" (www.example.com != example.com)
Related
The given scenario is a login page and another page with a user restriction.
What is the best practice to redirect the user automatically to the restricted page if he calls the login page but is already logged in?
The workflow should be:
User calls Login-page
TYPO3 detects that the user is already logged in
TYPO3 redirects the user to Restricted-page
Many thanks
Take a look at this extension : https://bitbucket.org/ideativedigital/t3-redirect40x/src/master/. I know it works with TYPO3 9 but you will probably need some adjustements if you need it to work with TYPO3 8.
In Typoscript you can use conditions to a) check if a user is logged in and b) check what page they are on. Then you can add some addtional headers to do the forwarding.
[usergroup = *] && [globalVar = TSFE:id = YOUR-LOGIN-ID]
config.additionalHeaders.cObject = COA
config.additionalHeaders.cObject {
10 = TEXT
10.value = HTTP/1.0 302 Temporary Redirect | Location: http://www.your-domain.com
20 = TEXT
20 {
typolink.parameter = YOUR-FORWARDING-ID
typolink.returnLast = url
}
}
[global]
usergroup can be * = all usergroups or you can put the actual ID of the usergroup(s) you want to forward. YOUR-LOGIN-ID should be the pid of the page where your login is. YOUR-FORWARDING-ID should be the id of the page you want to forward to
Is it possible to store all records of the news extension (ext:news) on the same storage page, but show only records, which are created by the loggedin backend user?
So the current backend user can just see and edit his own records? Admins should see all records of course.
No, this is not possible, since backend user permissions on record level are not implemented in TYPO3.
So you either have to separate the news records of the users in separate sysfolders or you could try to use hooks (e.g. $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['getTable']) or XClass to customize TYPO3 backend to your needs. I do not recommend the latter, since the TYPO3 backend permission system is complex and you would need to make sure to restrict record access in several parts of TYPO3 (e.g. recordlist, element browser, related news field, ...)
There are two ways to archive that:
If the backend user is not too much. You can just create a page(type
is folder) named with the backend user name. And in the backend user
module you can set the permission(Not for the group user but for the
single backend user only).
if the backend user is too much. and You just wanna set permissions for the group and all backend users are sharing the same rules. You can refer to Hook:https://docs.typo3.org/p/georgringer/news/main/en-us/Tutorials/ExtendNews/Hooks/Index.html so that the basic logic is like this:
2.1 get current logged-in user group.
2.2 if the group is Reporter, we can use the hook for the listing page:
$constraints[] = $query->equals('cruser_id', $be_id);
Edit(3/3/2022):
Hi Chris, Yes you are right.
Today, I have got a chance to dig into the news extension. I think we can still make it by the hook
in your ext_localconf.php
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][\TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList::class]['modifyQuery'][$_EXTKEY]
= \T3docs\SitePackage\Hooks\DatabaseRecordListHook::class;
(Please make sure the namespace is correct)
within the file : T3docs\SitePackage\Hooks\DatabaseRecordListHook.Create a function named modifyQuery:
public function modifyQuery($parameters,
$table,
$pageId,
$additionalConstraints,
$fields,
$queryBuilder)
{
if ($table === 'tx_news_domain_model_news') {
$tsconfig = $GLOBALS['BE_USER']->getTSConfig();
if (!empty($tsconfig['options.']['be_users'])) {
$be_users = $tsconfig['options.']['be_users'];
$queryBuilder->andWhere('cruser_id IN (' . $be_users . ')');
}
}
return $queryBuilder;
}
in the user Options tab set Tsconfg : options.be_users = 3,100
(3,100 is the be_user id. And the 2 two backend users's news will show up)
thus, it works for me.
My client has an old TYPO3 6.2 installation which has been rebuild in TYPO3 8.7.
In the old TYPO3 6.2 installation the fe_users table owns about 15.000 users with MD5/crypt(3) encrypted passwords (starting with $1$). The rebuild fe_users for the client in TYPO3 8.7 now has passwords based on the new crypt (starting with $pbkdf2-sha256$). So far, so good.
The old TYPO3 6.2 fe_users will be imported into the new database but I'm having issues on logging in with them using our own REST API (build in TYPO3 8.7), where the login using felogin are all successfull. After a successfull login by felogin the passwords are converted to their new encryption and I am able to login with the REST API. -- Logging in 15.000 users by felogin before the possibility of using the REST API is definitely not an option :)
The REST API does a comparison using \TYPO3\CMS\Saltedpasswords\.
tl;dr:
How do I check for a successfull encryption by \TYPO3\CMS\Saltedpasswords\ without first forcing them the usage of felogin?
Sample code of the REST API
The $byPasswordDecrypt in the code below is a decrypted value of the password, which is send encrypted using RNCryptor
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('fe_users');
$queryRows = $queryBuilder
->select('uid', 'username', 'password')
->from('fe_users')
->where(
$queryBuilder->expr()->eq('username', $queryBuilder->createNamedParameter($ogUser))
)
->execute();
// Fetch the rows
$queryFetch = $user = $queryRows->fetch();
// Now, check the salted-password from the database against the given password
if (\TYPO3\CMS\Saltedpasswords\Utility\SaltedPasswordsUtility::isUsageEnabled('FE')) {
$objSalt = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::getSaltingInstance($saltedPassword);
if (is_object($objSalt)) {
$success = $objSalt->checkPassword($byPasswordDecrypt, $queryFetch['password']);
}
}
If somebody could point me into the right direction to a successfull password-hash check, that would be absolutely great and I'd be so thankfull!
I have managed to fix this problem myself and posting the solution to my own question, hoping to help someone else with this issue.
TYPO3 6.2 (and probably lower) is hashing the passwords using a MD5-hash, starting with $1$. If everything set-up correctly, TYPO3 8.7 will hash the passwords using something like $pbkdf2-sha256$.
To check for old passwords, you should make an instance of the TYPO3\CMS\Saltedpasswords\Salt\Md5Salt. After you've done a successfull check using checkPassword by this instance, I'd recommend you update your database table using the given password and encrypting it by using \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory.
An examplecode for checking the old MD5 encrypted password:
$md5PasswordProcessor = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Saltedpasswords\\Salt\\Md5Salt');
$sampleLoginData = array(
'uname' => $usernameSample
'uident' => $unencryptedPassword,
'status' => 'login'
);
$frontEndUserAuth = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Authentication\\FrontendUserAuthentication');
$frontEndUserAuth->checkPid = false;
$info = $frontEndUserAuth->getAuthInfoArray();
$info['db_user']['username_column'] = 'email';
$user_db = $frontEndUserAuth->fetchUserRecord($info['db_user'], $sampleLoginData['uname']);
$passwordByMd5 = $md5PasswordProcessor->checkPassword($byPasswordDecrypt, $user_db['password']);
if($passwordByMd5 === true) {
// Check is correct, update your database here by, for example:
$objSalt = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::getSaltingInstance(null);
$saltedPassword = $objSalt->getHashedPassword($unencryptedPassword);
// And your queryBuilder should be written here
}
I hope I helped anyone else out, having this problem.
I have a facebook app that runs inside an iframe. After the user allow permissions from the app I'm expecting facebook to send me $_REQUEST variables that I use to retrieve user data and it is working well. The problem is after I put the users data in Laravel Session using Session::put() and then Session::save(), on the next request the session is gone. So my app cannot retrieve the Session anymore. I really don't know why during the test all of my browsers work, (Safari, Firefox, Chrome). So I put some error checking to email me everytime there is an Session Error and still I got 30+ emails per day telling that Chrome has no Session, and some users were posting about the App returning Error. I'm really struggling for this problem for days now. I've implemented some fix adding P3P headers and adding favicon on my site, still no avail.
Here is my code:
Route::filter('before', function()
{
// Do stuff before every request to your application...
header('P3P:CP="NOI DEV PSAi COM NAV OTR STP DEM HONK IDC DSP COR ADM DEVi TAIi CAO PSA PSD IVAi IVDi CONi HIS OUR IND CNT"');
//safari 3rd party fix cookie fix
if(isset($_SERVER['HTTP_USER_AGENT'])) {
if (! count($_COOKIE) > 0 && strpos($_SERVER['HTTP_USER_AGENT'], 'Safari')) {
if(strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome') == false) {
session_start();
$page_url = Config::get('custom.fb_page');
if (isset($_GET["start_session"]))
die(header("Location:" . $page_url));
$sid = session_id();
if (!isset($_GET["sid"]))
{
if(isset($_POST["signed_request"]))
$_SESSION["signed_request"] = $_POST["signed_request"];
die(header("Location:?sid=" . $sid));
}
if (empty($sid) || $_GET["sid"] != $sid)
die('<script>top.window.location="?start_session=true";</script>');
}
}
}
}
}
//and the code that sets Laravel Session
Route::any('tab/(:any?)', function ($res = null)
{
//$response = some_function_to_get_token($_REQUEST['signed_request']);
if($response && isset($response['oauth_token']))
{
Session::put('my_session_for_token', $response['oauth_token']);
Session::save();
$redirect = Redirect::to('my_awesome_page');
}
else
$redirect = Redirect::to('permission');
}
EDIT
I've already tried setting $_SESSION and commenting out Session::put() but it doesn't set my $_SESSION at all. Next thing I tried was uploading a sessionchecker.php script and tried it using the browser.
heres the code for session check:
<?php
error_reporting(E_ALL);
ini_set('display_errors', '1');
session_start();
if (isset($_SESSION['views']))
$_SESSION['views'] = $_SESSION['views'] + 1;
else
$_SESSION['views'] = 0;
echo '<pre>';
var_dump(session_id()); // I should stay the same
var_dump($_SESSION); // I should start at 0 and increase
echo '</pre>';
and it working as expected, Im suspecting that it has something to do with Redirect::to().
P.S. I've already tried configuring Laravel to use Cookie and File but still the error occurs.
This is not a Laravel problem. This is a classic Safari/Internet explorer 3rd party cookie problem.
Try googling for "safari cookie fix" or check out some of these questions here, for example:
Facebook Iframe App with multiple pages in Safari Session Variables not persisting
I have found that if I use the below typoscript I can redirect my users to the mobile version of the site which has its own tree in the backend of my typo3 site.
[useragent = *iPhone*]||[useragent = *iPod*]||[useragent = *Android*]
config.additionalHeaders = Location: http://m.example.com/
[end]
It is a simplified version of the site however so I want to have a return to full website link. But due to my above typoscript redirecting users to the m domain i can't get back to www.example.com.
Does anyone have any typoscript suggestions here?
You need an additional parameter in your link back which you can use to turn off the redirection.
Try something like this:
# check for mobile browser
[useragent = *iPhone*]||[useragent = *iPod*]||[useragent = *Android*]
config.additionalHeaders = Location: http://m.example.com/
[global]
# undo mobile redirect if mobile param is set
[globalVar = GP:nomobileredirect > 0]
config.additionalHeaders =
[global]
and redirect to http://www.example.com/?nomobileredirect=1 on your link back.
To keep a nomobileredirect-value in all generated links, add nomobileredirect to your linkVars, e.g.
config.linkVars = nomobileredirect,L
You can use another condition on a GET parameter and override the config.additionalHeaders later. Remember, TS is not a scripting language, but rather a static configuration. The last statement always wins and rendering starts only once all TS has been parsed.
You can also try to extend the above condition by an additional exclude of a GET parameter.