0

I need to create a custom SSO plugin. The way it should work is:

  1. User authenticates on 3rd party application
  2. 3rd party application calls a Joomla URL via POST request
  3. The URL that has been hit deals with authentication on Joomla's end
  4. User is logged in both on Joomla and on 3rd party application

I know how to create a custom plugin for authentication as I've done it in the past, but I can't find a way to expose a plugin URL for point 2. Is there a way to expose a plugin URL, or is there any other way to achieve the above? Users will register and login on the 3rd party application, but I still need them authenticated on the Joomla website. Thank you.

UPDATE

I have tried to implement the procedure outlined below, including the plugin from a component, but it's not working.

/components/com_testauth/controllers/sso.php

class TestAuthControllerSso extends JControllerLegacy
{
 public function auth() {
    JPluginHelper::importPlugin('user');
    JPluginHelper::importPlugin('authentication');
    $dispatcher = JEventDispatcher::getInstance();
    $options = '';
    $response = new \stdClass();
    $credentials = array();
    $credentials["username"] = "test";
    $credentials["password"] = "tset";
    $results = $dispatcher->trigger('onUserAuthenticate', array($credentials, 
     $options, &$response));

    return $results;
}

}

/plugins/authentication/test/test.php (This has been copied from Joomla documentation to test the functionality)

class PlgAuthenticationTest extends JPlugin
{
   function onUserAuthenticate( $credentials, $options, &$response )
    {
        
        /*
         * Here you would do whatever you need for an authentication routine with the credentials
         *
         * In this example the mixed variable $return would be set to false
         * if the authentication routine fails or an integer userid of the authenticated
         * user if the routine passes
         */
        $db = JFactory::getDbo();
    $query  = $db->getQuery(true)
        ->select('id')
        ->from('#__users')
        ->where('username=' . $db->quote($credentials['username']));

    $db->setQuery($query);
    $result = $db->loadResult();
    

    if (!$result) {
        $response->status = STATUS_FAILURE;
        $response->error_message = 'User does not exist';
    }

    /**
     * To authenticate, the username must exist in the database, and the password should be equal
     * to the reverse of the username (so user joeblow would have password wolbeoj)
     */
    if($result && ($credentials['username'] == strrev( $credentials['password'] )))
    {
        $email = JUser::getInstance($result); // Bring this in line with the rest of the system
        
        $response->email = $email->email;
        
        $response->status = JAuthentication::STATUS_SUCCESS;
        
        return true;
        
    }
    else
    {
        $response->status = JAuthentication::STATUS_FAILURE;
        $response->error_message = 'Invalid username and password';
    }
    }
    
    
}

The problem is that I can log in ok if I log in through the log in form, but I can't log in if I call the component controller from the URL. The credentials of the user are hard-coded to avoid mistakes, so that the authentication should always be correct.

The process I followed is:

  1. Created a component that includes the authentication plugin. a. Please note that I'm including the whole "authentication" plugin, including the single plugin doesn't seem to work.
  2. Created an authentication plugin
  3. Visited the controller URL - index.php?option=com_testauth&task=sso.auth

UPDATE 2

I have come up with another solution, which unfortunately it's not working at 100%, but it may help people in the future.

What I did is:

  1. Created an Ajax plugin, and installed it as an Ajax plugin in Joomla to expose the URL, code as follows:

`

function onAjaxSSO()
{
$app = JFactory::getApplication();
$input = $app->input;
$app->setHeader('X-Robots-Tag', 'noindex, nofollow');   
$task = $input->get("task", "", "cmd"); 
$app->logout(JFactory::getUser()->id, array()); 

//Do all the security checks to see if the call is legit or not and if it has all the right details.
[...]

//Pass the details to the authentication plugin
$loginResponse = $app->login(array('username' => $username, 'email' => $email, 'password' => $password, 'name' => $forename.' '.$surname), array('silent' => true));    

//Check what is the response from the authentication plugin and display the message on the API response

if($loginResponse === true) {
    $app->setHeader('status', 200, true);
    $result = "";
    echo new JResponseJson($result, 'Success - User is authenticated', false);
    return $app->close();
}
else {
    $app->setHeader('status', 401, true);
    $result = '';
    echo new JResponseJson($result, 'Unauthorized - User is not authenticated', true);
    return $app->close();
}
}

`

  1. Created an authentication plugin, this deals with all the authentication stuff. Code as follows, parts are missing for brevity:

`

function onUserAuthenticate( $credentials, $options, &$response )
{

$app = JFactory::getApplication();
        
//No log in for admins
if ($app->isClient('administrator')) {

    $response->status        = JAuthentication::STATUS_FAILURE;
    return false;
}

//We check Joomla database to see if the details are the same
[...]

//Authenticate the user if everything looks legit

    $user                    = JUser::getInstance($joomlaId);
    $response->email         = $user->email;
    $response->fullname      = $user->name;
    $response->username      = $user->username;
    $response->language      = $user->getParam('language');
    $response->status        = JAuthentication::STATUS_SUCCESS;
    $response->error_message = '';

}

`

When I call the API exposed with the Ajax plugin, I get a "true" response from the plugin, the authentication goes fine (I can see the user being updated/inserted on the database), and I can also see, from the back-end, the user in the list of "Active users", but nothing changes on the front-end. The user is not properly logged-in, the joomla_user_state cookie has not been created and everything seems like the user has never logged in. If I try to print

echo JFactory::getUser()->id

I get 0.

10
  • Welcome to JSE. Please take our tour. Please continue to attempt to resolve you issue while you wait for support/feedback. If you manage to resolve your own issue, please post an educational answer to your question.
    – mickmackusa
    Aug 24 '20 at 14:12
  • I achieved this by authenticating a WordPress user in Joomla (same domain; two sites - one Joomla, one Wordpress) by creating a simple Joomla component, which is easily exposed via URL. In the component, I used a task and some parameters to call the authentication plugin. The params were non-descript but essentially used to check in the authentication plugin if the user was currently logged in on the WordPress site. All the auth plugin has to do is return true/false. Might be worth thinking about - at the time (circa 5 years ago) - there was no other method I found which would do this.
    – Grant G
    Aug 24 '20 at 21:22
  • Thank you, @GrantG. So you are saying that I can achieve this by triggering the onUserAuthenticate event of a custom authentication plugin? Is this achieved by using JPluginHelper as below? JPluginHelper::importPlugin('mycustomauth'); $dispatcher = JEventDispatcher::getInstance(); $dispatcher->trigger('onUserAuthenticate', $data);
    – Kabal
    Aug 25 '20 at 10:44
  • Yes, that is correct. You would use your mycustomauth plugin to handle $data and return true/false to authenticate the user.
    – Grant G
    Aug 25 '20 at 11:27
  • 1
    @Kabal this could be falling down for a number of reasons. There are a multitude of scenarios you may need to go down, which is probably too broad a discussion for a comment board like this; but to begin, have you confirmed your component controller is calling the sso auth()?
    – Grant G
    Aug 31 '20 at 17:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.