3

I've got a website that uses an AJAX call to login a user. To secure this, I've added a token to the login form - https://docs.joomla.org/How_to_add_CSRF_anti-spoofing_to_forms

the problem is that, when the user is inactive for a while, the Joomla auto logout is fired. And therefor my token dosen't work.

How do I refresh the token by AJAX before making the login call?

----------------------------------------------------- More details: -----------------------------------------------------------

The normal operation of the form is omitted in AJAX by:

jQuery('#login-user').click(function(e){            
e.preventDefault(); 

And then the login AJAX call is send:

form = jQuery('#userForm'); 

jQuery.ajax({
    url: 'index.php?option=com_content&format=ajax&view=article&task=loginUser&tmpl=component',
    type: 'post',
    dataType: 'html',
    data: {
        form: jQuery(form).serializeArray()
    },
    async: true,
    success: function(response){
        var result = jQuery.parseJSON(response);

        if ( result.loggedIn == 1 ) {                       
            //User logged in
            jQuery('#loginModal').modal('hide');
            window.location.href = window.location.pathname + window.location.search + window.location.hash;// reload page creates a history entry
        }
        else {                  
            //User not logged in    
            console.log("not");         
        }               
    }
}); 

BUT: the problem is that, when the user is inactive for a while, the Joomla auto logout is fired. And therefor my token dosen't work.

How do I refresh the token by AJAX before making the login call?

5
  • So this isn't just about "securing ajax calls", this is "How do I perform an ajax call for a logged in user while passing a token AND when the user's session has expired, offer a re-login popup, then after re-logging in, the token must be refreshed and the initial ajax operation should be re-engaged?" Golly, this is certainly a reasonable desire, but definitely a complex thing to answer. Commented Oct 14, 2018 at 0:08
  • Thanks @mickmackusa! I see what you mean. Next time I´ll split it op in different questions that makes more sense that way. Commented Oct 14, 2018 at 14:22
  • Unfortuntely, questions that are Too Broad are either 1. not completely answered or 2. require a massive, comprehensive write up. The first is a real let down for googlers who thinks they've struck gold in the search results only to find that there isn't a full answer available. The second is simply too much reading for the average researcher. Both are better than nothing, but to make JSE spectacularly valuable, we should all endeavor to make the site clean, comprehensive, searchable, and clear. Commented Oct 14, 2018 at 14:31
  • @mickmackusa I get what you see, I’ll update the question soon! Commented Oct 14, 2018 at 14:36
  • @mickmackusa The question is updated now :) Commented Oct 14, 2018 at 15:17

2 Answers 2

4

I wanted to answer your earlier question about this yesterday, but someone was already answered this partially for you. So according to me your original Login Form token field should be a bit changed like the following:

<form method="post" action="#" id="userForm">
    <label for="username">Brugernavn</label>    
    <input type="text" value="" name="username">    
    <label for="password">Password</label>  
    <input type="password" value="" name="password">
    <?php echo '<input id="token" type="hidden" name="' . JSession::getFormToken($forceNew=true) . '" value="1" />'; ?>

    <button id="login-user">Login</button>
</form>

This way the token function forced to generate always a new token which could be sent with the AJAX query anytime (your original AJAX query might be changed a bit too to forward the token created this way and checking the token in your called function should may be re-formulated too. Maybe those are OK as they are now, you'll test it). I hope this can help you in the question.

Now the above solution is generating a new token for the Form only when the site is refreshed. and that is not what you are looking for, as we found out a bit later. And I will not leave this subject without closing it if we went into this now.

So, what is the real problem here?

Of course as we talked about it (in the added comments), you could get a fresh token with an initial AJAX call to a function of refreshingToken() (which would be a custom function you could create with few lines of codes). But this function would also delete the old request/session token and would create a new one (and that would also mean a new session and new request). This is due to security reasons.

Here is the problem and the most possible solution of what you want to accomplish: The real solution to your problem is about sessions and not about getting new tokens.

After you explained finally that you want to solve the problem of the logged in User when he is i.e. editing an article and it takes a little longer time for him to finish the editing, and this user has gotten logged out by the system, then you want them to be logged in again without redirection and losing their unfinished article for example.

A working solution of this problem is how Joomla solved it with keeping the session alive with a core Joomla function.

So if you call the following function at the top of your particular pages’ layout files (or in your Form layout file):

JHtml::_('behavior.keepalive');

Then It will just keep the user's session alive and that’s it, your problem is solved (we can say), since the session will not expire on the article editing page. The user will not lose his work as he won’t be logged out during an important article writing, editing.

Now, do you have to create your own AJAX based login form to add keepalive() function to the com_content article edit page for example?

No, you do not.

KEEPING THE SESSION ALIVE ON DIFFERENT PAGES OF JOOMLA

In Joomla, at the top of the login module (mod_login) the JHtml::_('behavior.keepalive'); is included, thus if you publish this login module on the Article Edit pages (or menus) for example, then the user session will be kept alive on those pages, so it means that your editor User will not lose his work, since he will not be logged out of his session, since the keepalive() function (via a javascript function) will refresh his session's time regularly.

And finally

If you still want to, you can also include JHtml::_('behavior.keepalive'); on the top of your custom Login Form layout file placed on the 'article edit' page and that will prevent of loging users out during editing and of losing an unfinished article at the side of your User.

Another possible solution:

  1. You could also create a plugin which shows a remaining session time on article edit pages in a module and there could be a button to restart the session or fork the session. The Joomla/CMS/Session/Session class has functions for that which could be called (it should be studied more by myself too). So the user instead of logging in just can push a button to restart the session. (later edit: I have checked these Session functions and unfortunately start(), restart(), fork(), all of these functions destroy the current session, so these are not working solutions of the problem in question).

I am sorry for the very long description but this was the only way to clear the problem and the subject at an acceptable level. I hope this is gonna clear the subject more and will help you.

13
  • Thanks!!... Would this mean that, when a user is auto logged out, I have to to first make an AJAX call to fetch the new token and then afterwards do my login AJAX? :) Commented Oct 14, 2018 at 14:23
  • No, I do not think so. First just change your Form token field the way I wrote up here and then use what you already have. The point is that the Form at submit always have to create a new token for the new request cycle (that way there is no such thing as invalid token in that cycle because the token is always fresh with the new request). It is theoretically that simple and Joomla already has a solution for that (as it is given in the Form above).
    – Zollie
    Commented Oct 14, 2018 at 15:18
  • So again clear it: 1. You have a Form. 2. You have the AJAX call. 3. You have the function which checks the token and log the user in.
    – Zollie
    Commented Oct 14, 2018 at 15:20
  • Thanks!! I’ll try it out and let you know the result Commented Oct 14, 2018 at 15:22
  • Hmmm. I can't get this to work. Only if the page is reloaded it will work :/ ...The token is only refreshed on a page reload, so when I fire the AJAX call when the user is auto logged out by Joomla but the page haven't reloaded, then the token is the same and will be denied Commented Oct 14, 2018 at 17:55
4

Playing with the sessions is usually not a very safe thing to do - you could create more problems by trying to find a solution.

You can do one (or both) of the following:

  • Increase the Session Lifetime under System, Global Configuration to a higher number, such as 1440 (1 day). This will minimize the problem, but will not eliminate it. Another problem with this approach is that you may risk flooding your session table if your website gets a huge amount of traffic. See here.
  • Add, to your template, an Ajax request that will subtly load any page on your website every 30 minutes or so.

The previous answer mentions using JHtml::_('behavior.keepalive');, which should also technically work, but I do remember (and I might be wrong) that it doesn't work well when page caching is enabled.

1
  • 1
    I agree with you that setting longer session time would be the simplest solution to this problem. JHtml::_('behavior.keepalive'); had issues but only when progressive caching was set on Joomla. But in that case there were problems with other javascript invoked functions at the same time.
    – Zollie
    Commented Oct 15, 2018 at 15:03

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.