Handling of login timeouts

Handling of login timeouts

rf1234rf1234 Posts: 3,103Questions: 90Answers: 429
edited February 10 in Editor

This is more about sharing my experience, but maybe you can help me to understand a few things a little better.

A few years ago I set a simple login timeout after 20 minutes and redirected users to my homepage when this occured.

Pretty simple like this:

var timeoutTwenty = 1200000; //20 minutes = 20 * 60,000 milli-seconds
loginTimeoutID = setTimeout("logout()", timeoutTwenty);

function logout() {
    $.ajax({
        type: "POST",
        url: 'actions.php?action=logout',
        async: true,
        success: function () {
            //set a cookie for one minute to highlight login
            Cookies.set('redirect', 'logout', {expires: 1/1440, secure: secureMode});
            window.location.reload(true);
        }
    });
}

Usually that works. But sometimes it doesn't. I still haven't understood why: Maybe because some client devices hibernate or get into power safe mode after a while so "window.location.reload(true)" wasn't executed?! Don't know.

But on many occasions users came back to their computer and the last screen was still open. Then they started doing something - and got a system error because they were logged out. In that case 95% of my users would do a page refresh - and then logged in again. But some users didn't - and went on making entries. The thought the system error was just a "warning" :neutral:

So I had to do something about this. I also had to something about people entering wrong dates inspite of date masking and using a date picker. Somebody managed to enter "10.19.2029" as a date! After 7 years of operation that came as a surprise.

So this is my solution for both situations. One is for the dates, one is for being logged out while using Editor and another one is for being logged out and using other functionality that requires to be logged in. Maybe useful for others to.

//date validator for all Editors
$(document).on( 'initEditor', function ( e, inst ) {
    // Attach an 'initSubmit' event to all Editors
    inst
    .on( 'initSubmit', function (e, action) {
        if ( action === "remove" ) {
            return true;
        }
        var that = this;
        //we only need the visible fields, not all of them like in that.order();
        var fieldArr = that.displayed();
        $.each(fieldArr, function(key, name) {
            var fld = that.field(name);
            var node = $( fld.node() );
            if ( node.hasClass('DTE_Field_Type_datetime') && 
                 ( ! node.find('input').hasClass('timeEnglishGerman') ) ) {
                fld.error("");
                if ( fld.val() > " " ) {
                    //we are not using strict mode in moment.js so that 28.12.2017 09:42 is also
                    //recognized as a date!!
                    if ( ! moment(fld.val(), 'L').isValid() ) {
                        fld.error( lang === 'de' ? 'Ungültiges Datum!' : 'Invalid Date!' );
                        return false;
                    }
                }
            }
        });
        // If any error was reported, cancel the submission so it can be corrected
        if ( that.inError() ) {
            return false;
        }
    })
    .on( 'submitError', function (e, xhr, err, thrown, data) {
        //the user was logged out when doing the editing!
        var span = '<span class="blink3" style="font-size:18px;">';
        if ( xhr.status == 401 ) { //Unauthorized
            this.error( lang === 'de' ? (span + 'Sie sind nicht mehr eingeloggt und werden umgeleitet!</span>') : 
                                        (span + 'You are no longer logged in and are being redirected!</span>') );
            if ( this.display() ) {
                setTimeout(function() {
                    window.location.reload(true);
                }, 3000);
            } else { //there is no form displayed: the waiting time doesn't make sense
                window.location.reload(true);
            }
        } else {
            var error_text = lang === 'de' ? (span + 'Sytemfehler! Bitte kontaktieren Sie den technischen Support!</span><br>') : 
                                             (span + 'Sytem error! Please contact tech support!</span><br>');
            this.error( error_text + xhr.responseText ); 
        }
    });
});
$(document).ajaxError(function myErrorHandler(event, xhr, ajaxOptions, thrownError) {
    if ( xhr.status == 403 ) { //Forbidden
        alert( lang === 'de' ? 'Sie sind nicht mehr eingeloggt!' : 
                               'You are no longer logged in!' );
        window.location.reload(true);
    }
});

Replies

  • rf1234rf1234 Posts: 3,103Questions: 90Answers: 429
    edited February 10

    The PHP code was pretty simple. Here is what I use to check being logged in when using Editor (or rather before using Editor):

    //do nothing if we aren't logged in!
    if ( ! isset($_SESSION['id']) ) {
        http_response_code(401);
        exit();
    }
    

    And for the other editing situations not using Editor:

    if ( ! isset($_SESSION['id']) ) {
        http_response_code(403);
        exit();
    }
    
  • allanallan Posts: 64,311Questions: 1Answers: 10,621 Site admin

    setTimeout takes a 32 bit int (as I understand it), and you are no where need the max of that range, so I'm not sure why the setTimeout out wouldn't trigger there I'm afraid. As you say perhaps there is something in the energy saving that is causing the issue, or possibly something else on the page is cancelling the timer (it is identified by a simple int, so anything could cancel it - that would be a fund way of messing with someone - loop of an int range and run clearTimeout!).

    You could try setInterval and see if that helps perhaps?

    Regardless of that - thanks for sharing this with everyone else - that looks like a nice way of handling both cases!

    Allan

  • rf1234rf1234 Posts: 3,103Questions: 90Answers: 429
    edited February 10

    so I'm not sure why the setTimeout out wouldn't trigger there I'm afraid.

    First of all: Thanks for your help with this, Allan!

    Well, the setTimeout does trigger because people are actually logged off. What doesn't work is "window.location.reload(true);" because they are still on the page on which they were logged out. The browser seems to be not responding sometimes ... If the reload was executed my client script would check whether they are logged in - and if not redirect them to my homepage.

    Hence, the users can keep on clicking and making entries on the original page which causes system errors because the server scripts require the PHP session to be intact. Typical scenario: They are working on something, then go for lunch, come back after 45 minutes. Their workstation is hibernating or whatever. They reactivate their workstation and return to the browser which in some cases has the same page still open. They are logged off now - but they don't see it because there is no login popup and they are not on the homepage either.

    That was the problem - well not with many users but a few ... Most users are making a page refresh when this happens. Very few sent me an error report. But that should be over now, I guess.

  • allanallan Posts: 64,311Questions: 1Answers: 10,621 Site admin

    That's got to be a tab "powering down" if not active action by the browser. Do you know if it is specific to Safari users, or Chrome, Firefox, etc? Safari I know prioritizes battery life, so I can see it doing something like that.

    Another option might be to try a setInterval to query the server to check if the session is still valid and then redirect the page (although that might well hit the same issue).

    Interesting one...!

    Allan

  • rf1234rf1234 Posts: 3,103Questions: 90Answers: 429

    My users mostly use Edge, Chrome and Firefox. Hardly anyone uses Safari.

    "setInterval" could be a good idea though. If the interval is short enough, it would query the server coming back from "sleep mode" BEFORE the user can make invalid entries. I should have considered that earlier :smile: Could have saved me some time.

    But now I have my new solution in place which also works in the unlikely event that the interval is too long to prevent invalid user entries ...

    Thanks for your help, Allan.

    Roland

  • rf1234rf1234 Posts: 3,103Questions: 90Answers: 429

    To whom it may concern :smiley:

    The default of my state saving application is saving the data on the server in a database. Most users have that activated. Some don't have state saving activated. So those are excluded.

    Edge is the most popular browser in the German public sector I guess. Microsoft is very dominant. Then of course Chrome. And Firefox is on the decline. Hardly anyone uses my application with a mobile phone - or uses Safari.

  • allanallan Posts: 64,311Questions: 1Answers: 10,621 Site admin

    That is interesting - thanks for sharing that!

    Allan

Sign In or Register to comment.