0
votes

My understanding to Joomla login is as follows:

  1. When the user click login, the following snippet will run (components/com_users/views/login/tmpl/default_login.php):

    <form action="<?php echo JRoute::_('index.php?option=com_users&task=user.login'); ?>"method="post">
    
        <fieldset>
            <?php foreach ($this->form->getFieldset('credentials') as $field): ?>
                <?php if (!$field->hidden): ?>
                    <div class="login-fields"><?php echo $field->label; ?>
                    <?php echo $field->input; ?></div>
                <?php endif; ?>
            <?php endforeach; ?>
            <?php if (JPluginHelper::isEnabled('system', 'remember')) : ?>
            <div class="login-fields">
                <label id="remember-lbl" for="remember"><?php echo JText::_('JGLOBAL_REMEMBER_ME') ?></label>
                <input id="remember" type="checkbox" name="remember" class="inputbox" value="yes"  alt="<?php echo JText::_('JGLOBAL_REMEMBER_ME') ?>" />
            </div>
            <?php endif; ?>
        <button type="submit" class="button"><?php echo JText::_('JLOGIN'); ?></button>
            <input type="hidden" name="return" value="<?php echo base64_encode($this->params->get('login_redirect_url', $this->form->getValue('return'))); ?>" />
            <?php echo JHtml::_('form.token'); ?>
        </fieldset>
    </form>
    
  2. In which, login() function is called from ( \components\com_users\controllers\user.php)

    public function login() { JSession::checkToken('post') or jexit(JText::_('JInvalid_Token'));

    $app = JFactory::getApplication();
    
    // Populate the data array:
    $data = array();
    $data['return'] = base64_decode(JRequest::getVar('return', '', 'POST', 'BASE64'));
    $data['username'] = JRequest::getVar('username', '', 'method', 'username');
    $data['password'] = JRequest::getString('password', '', 'post', JREQUEST_ALLOWRAW);
    $lang = JRequest::getVar('lang','post');
    
    // Set the return URL if empty.
    if (empty($data['return'])) {
        $data['return'] = 'index.php?option=com_users&view=profile';
    }else {
        if($lang){
            $lang = mb_substr($lang, 0, 2);
            $data['return'] .= '&lang='.$lang;
        }
    }
    
    
    // Set the return URL in the user state to allow modification by plugins
    $app->setUserState('users.login.form.return', $data['return']);
    
    // Get the log in options.
    $options = array();
    $options['remember'] = JRequest::getBool('remember', false);
    $options['return'] = $data['return'];
    
    // Get the log in credentials.
    $credentials = array();
    $credentials['username'] = $data['username'];
    $credentials['password'] = $data['password'];
    
    // Perform the log in.
    if (true === $app->login($credentials, $options)) {
        // Success
        $app->setUserState('users.login.form.data', array());
        $app->redirect(JRoute::_($app->getUserState('users.login.form.return'), false));
    } else {
        // Login failed !
        $data['remember'] = (int)$options['remember'];
        $app->setUserState('users.login.form.data', $data);
        $app->redirect(JRoute::_('index.php?option=com_users&view=login', false));
    }
    

    }

The username and password are retrieved here and then

  1. Then function login($credentials, $options = array()) is called (libraries/legacy/application/application.php):

    public function login($credentials, $options = array()) { // Get the global JAuthentication object. jimport('joomla.user.authentication');

        $authenticate = JAuthentication::getInstance();
        $response = $authenticate->authenticate($credentials, $options);
    
        if ($response->status === JAuthentication::STATUS_SUCCESS)
        {
            // validate that the user should be able to login (different to being authenticated)
            // this permits authentication plugins blocking the user
            $authorisations = $authenticate->authorise($response, $options);
            foreach ($authorisations as $authorisation)
            {
                $denied_states = array(JAuthentication::STATUS_EXPIRED, JAuthentication::STATUS_DENIED);
                if (in_array($authorisation->status, $denied_states))
                {
                    // Trigger onUserAuthorisationFailure Event.
                    $this->triggerEvent('onUserAuthorisationFailure', array((array) $authorisation));
    
                    // If silent is set, just return false.
                    if (isset($options['silent']) && $options['silent'])
                    {
                        return false;
                    }
    
                    // Return the error.
                    switch ($authorisation->status)
                    {
                        case JAuthentication::STATUS_EXPIRED:
                            return JError::raiseWarning('102002', JText::_('JLIB_LOGIN_EXPIRED'));
                            break;
                        case JAuthentication::STATUS_DENIED:
                            return JError::raiseWarning('102003', JText::_('JLIB_LOGIN_DENIED'));
                            break;
                        default:
                            return JError::raiseWarning('102004', JText::_('JLIB_LOGIN_AUTHORISATION'));
                            break;
                    }
                }
            }
    
            // Import the user plugin group.
            JPluginHelper::importPlugin('user');
    
            // OK, the credentials are authenticated and user is authorised.  Lets fire the onLogin event.
            $results = $this->triggerEvent('onUserLogin', array((array) $response, $options));
    
            /*
             * If any of the user plugins did not successfully complete the login routine
             * then the whole method fails.
             *
             * Any errors raised should be done in the plugin as this provides the ability
             * to provide much more information about why the routine may have failed.
             */
    
            if (!in_array(false, $results, true))
            {
                // Set the remember me cookie if enabled.
                if (isset($options['remember']) && $options['remember'])
                {
                    // Create the encryption key, apply extra hardening using the user agent string.
                    $privateKey = self::getHash(@$_SERVER['HTTP_USER_AGENT']);
    
                    $key = new JCryptKey('simple', $privateKey, $privateKey);
                    $crypt = new JCrypt(new JCryptCipherSimple, $key);
                    $rcookie = $crypt->encrypt(json_encode($credentials));
                    $lifetime = time() + 365 * 24 * 60 * 60;
    
                    // Use domain and path set in config for cookie if it exists.
                    $cookie_domain = $this->getCfg('cookie_domain', '');
                    $cookie_path = $this->getCfg('cookie_path', '/');
    
                    // Check for SSL connection
                    $secure = ((isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on')) || getenv('SSL_PROTOCOL_VERSION'));
                    setcookie(self::getHash('JLOGIN_REMEMBER'), $rcookie, $lifetime, $cookie_path, $cookie_domain, $secure, true);
                }
    
                return true;
            }
        }
    
        // Trigger onUserLoginFailure Event.
        $this->triggerEvent('onUserLoginFailure', array((array) $response));
    
        // If silent is set, just return false.
        if (isset($options['silent']) && $options['silent'])
        {
            return false;
        }
    
        // If status is success, any error will have been raised by the user plugin
        if ($response->status !== JAuthentication::STATUS_SUCCESS)
        {
            JError::raiseWarning('102001', $response->error_message);
        }
    
        return false;
    }
    

The question

Can I run the first script (step 1) using JavaScript? and also pass the credentials via JavaScript?

The reason behind it is that I need to login to the website from a mobile App that is using JavaScript. I can pass the credentials and I think if it possible to pass to Joomla login. If that is possible, what are the steps/logic I need to implement?

1

1 Answers

0
votes

"The reason behind it is that I need to login to the website from a mobile App"

why not make http post request to user.php?

  1. do post request to login page
  2. grab cookies
  3. do post request to gather data
  4. grab input stream
  5. process response stream