3

I am having an issue with the ACL of my Joomla API. I created this using the TechJoomla api component.

I have the following code to handle post requests on my api.

<?php
    
    use Joomla\CMS\Factory;
    
    class WdtoptionsApiResourceOptions extends ApiResource
    {
        public function post()
        {
            $user = Factory::getUser();
            $accessLevels = $user->getAuthorisedViewLevels();
            $result = new \stdClass;
            
            //check the user has the required access levels.  
            if (!in_array(9, $accessLevels))
            {
                $result-> options->{'Error'} = 'Could not access api. Are you logged in?';  
            }
            else
            {
                //I process the response for a valid user here.         
            }
            $this->plugin->setResponse( $result );
        }
    }
    ?>

For a user who has selected the 'Remember Me' check box at the login page it works correctly.

For a user who has not selected the 'Remember Me' check box at the login page, the error code appears and the user is immediately logged out.

How do I change this code to deal with users that don't have a 'remember me' cookie set?

Are these users still 'logged in'? Or do they fall into some other category?

I suspect the answer is to use the JFactory::getSession() function described here. But I can't work out how to use this function. https://docs.joomla.org/Using_the_JFactory_class

1
  • Solved it. Techjoomla's module was doing it's own authorisation check using JWT and firebase. Editing their code to remove this functionality solved the problem. Not much point reproducing the edits here.
    – Huw Evans
    Commented Apr 25, 2021 at 16:26

2 Answers 2

2

The problem was that techjoomla's api package had it's own functions for ACL that were designed to work with mobile phone apps. These introduced their own logic for determining whether a user was logged in.

To solve the issue I simply commented out the functionality (and deleted the relevant files to save some disk space).

Below is an excerpt from my edited file: ../site/api.php This shows the lines that must be edited out to reproduce this solution.

Please note that this code is still copyright Techjoomla and is licenced under GNU GPLv2

@copyright Copyright (C) 2009-2014 Techjoomla, Tekdi Technologies Pvt. Ltd. All rights reserved. @license GNU GPLv2 http://www.gnu.org/licenses/old-licenses/gpl-2.0.html

defined('_JEXEC') or die('Restricted access');

jimport('joomla.application.component.controller');

$library_path = JPATH_COMPONENT . '/libraries';

JLoader::register('APIController', $library_path . '/controller.php');
JLoader::register('APIModel', $library_path . '/model.php');
JLoader::register('APIView', $library_path . '/view.php');
JLoader::register('APIPlugin', $library_path . '/plugin.php');
JLoader::register('APIError', $library_path . '/error.php');
JLoader::register('ApiException', $library_path . '/exception.php');
JLoader::register('APICache', $library_path . '/cache.php');
JLoader::register('APIResource', $library_path . '/resource.php');

//I don't think we need the following lines for the WDT.  HE.

//JLoader::register('APIAuthentication', $library_path . '/authentication.php');
//JLoader::register('APIAuthenticationJfbconnect', $library_path . '/authentication/jfbconnect.php');
//JLoader::register('APIAuthenticationKey', $library_path . '/authentication/key.php');
//JLoader::register('APIAuthenticationLogin', $library_path . '/authentication/login.php');
//JLoader::register('APIAuthenticationSession', $library_path . '/authentication/session.php');
JLoader::register('APIHelper', $library_path . '/helper.php');
JTable::addIncludePath(JPATH_ROOT . '/administrator/components/com_api/tables');
JLoader::discover('API', JPATH_COMPONENT . '/libraries/exceptions');

$app = JFactory::getApplication();

$view = $app->input->get('view', '', 'CMD');

I also commented out the follow code that called the libraries listed above. This code is in ../site/libraries/plugin.php

//$user = APIAuthentication::authenticateRequest();
//$this->set('user', $user);
//$session = JFactory::getSession();
//$session->set('user', $user);

//$access = $this->getResourceAccess($resource_name, $this->request_method);

//if ($access == 'protected' && $user === false)
//{
//  ApiError::raiseError(403, APIAuthentication::getAuthError(), 'APIUnauthorisedException');
//}

//if (! $this->checkRequestLimit())
//{
//  ApiError::raiseError(403, JText::_('COM_API_RATE_LIMIT_EXCEEDED'), 'APIUnauthorisedException');
//}
1

Even though you have found a solution to your issue I thought you might still like to understand what I think is going on.

'Remember Me' doesn't keep a user logged in as you might think, it actually stores a Cookie in the browser and when the user returns to your website the Cookie is checked and it will then log the user on without prompting them for a username or password.

So what is happening in your description is a user requests the API, a 'Remember Me' Cookie is found in the browser and that user is logged in automatically and the API code is happy that they are logged in.

Anyone without a 'Remember Me' Cookie is therefore not logged automatically in and they fail the check in your post function, not because "...the error code appears and the user is immediately logged out.", it is because they were never logged in in the first place and this generated the error message.

If you look at examples/documentation on AJAX you will see many suggest the use of a Token that is passed to API to identify the requester and that they are logged in already, otherwise the API has no idea about the state of the requester and assumes they are not logged in.

1
  • Thank you for your answer, but this only partially correct. While I don't understand it completely, the issue must have been a conflict between the token authentication code and the standard joomla acl. To fix it I commented out/deleted the functions that were looking for tokens. Now it just uses the ACL of the rest of the site (which is what I wanted). It's not quite a bug because I am using the code in a different way to it's writer's intent. I didn't have to change my own code at all and yet The 'remember me' cookie is no longer required for the code the function.
    – Huw Evans
    Commented Apr 30, 2021 at 11:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.